Compare commits

..

78 Commits
7.2.0 ... 8.0.0

Author SHA1 Message Date
Daniel García Aubert
df10cfe641 Release 8.0.0 2019-11-13 13:07:00 +01:00
Daniel G. Aubert
09d3e8aabb Merge pull request #1139 from CartoDB/fix/bad-aggregation-method-overview
Validate aggregation method is either sum or count
2019-11-13 10:11:28 +01:00
Esther Lozano
f17411916f Remove unnecessary config in tests 2019-11-12 17:43:03 +01:00
Esther Lozano
75583f67c5 Use last version for map config in tests 2019-11-12 14:54:25 +01:00
Esther Lozano
bb745b0318 Update test/acceptance/dataviews/overviews-test.js
Co-Authored-By: Daniel G. Aubert <danielgarciaaubert@gmail.com>
2019-11-12 14:48:37 +01:00
Raúl Marín
3834aeb73f Merge pull request #1140 from Algunenano/local_password
Fix multiple DB login issues
2019-11-12 13:23:34 +01:00
Raúl Marín
aa09c079f6 Fix multiple DB login issues 2019-11-12 13:15:32 +01:00
Raúl Marín
3c586caba4 Qualify calls to cartodb extension so having it in the search_path isn't necessary 2019-11-12 13:15:32 +01:00
Esther Lozano
b05740048c Update NEWS.md 2019-11-12 12:48:22 +01:00
Esther Lozano
2b5ed21207 Remove only in tests :P 2019-11-12 12:37:24 +01:00
Esther Lozano
acecb88efb Validate aggregation method is either sum or count 2019-11-11 18:14:30 +01:00
Simon Martín
990aaadc16 Merge pull request #1134 from CartoDB/better-redis-logging
Adding a logger to MapStore
2019-10-29 12:10:00 +01:00
Simon Martín
0c572b5947 NEWS 2019-10-29 11:37:16 +01:00
Simon Martín
3e7c294989 linter 2019-10-29 11:32:27 +01:00
Simon Martín
8a02156ac0 fix tests 2019-10-29 10:31:31 +01:00
Simon Martín
c4a75de0d8 windshaft 5.6.4 2019-10-28 18:15:15 +01:00
Simon Martín
db03bcdf8f windshaft logger by config param 2019-10-28 15:41:46 +01:00
Simon Martín
dd5825c770 using a new logger 2019-10-28 11:55:43 +01:00
Simon Martín
080f93f6de passing logger to MapStore 2019-10-24 17:34:46 +02:00
Simon Martín
df931d95a3 using github:cartodb/windshaft#better-redis-logging 2019-10-24 17:34:30 +02:00
Daniel G. Aubert
9fd1a3c663 Merge pull request #1131 from CartoDB/coherent-cache-invalidation
Coherent cache invalidation
2019-10-21 16:41:28 +02:00
Daniel García Aubert
8a781d241c Typo 2019-10-21 16:22:26 +02:00
Daniel García Aubert
be4d610de1 Use released version of cartodb-query-tables 0.7.0 2019-10-21 16:17:54 +02:00
Daniel García Aubert
736d3460d9 Update development branch 2019-10-21 13:46:29 +02:00
Daniel García Aubert
f844d70275 Replace http --> https. I swear, I'm not a spy 2019-10-21 11:32:56 +02:00
Daniel García Aubert
0c9cfefcd0 Please jshint, can you be a regular linter? 2019-10-21 11:13:54 +02:00
Daniel García Aubert
8ed187b0f5 Do not set Last-Modifed to January 1st 1970 when cache buster ins layergroup token is 0. In this case, 0 means we don't know when the resource was updated for the last time. 2019-10-21 11:01:05 +02:00
owayss
e5bada81dc Merge pull request #1132 from CartoDB/default_to_stdout_logging
Default to stdout logging on dev environment
2019-10-17 14:13:28 +02:00
Owayss Kabtoul
655f817033 Default to stdout logging on dev environment 2019-10-17 13:04:10 +02:00
Daniel García Aubert
ebff2ac9f2 Please JSHint 2019-10-15 13:27:40 +02:00
Daniel García Aubert
5a7ffcf499 Be able to synchronize the TTL of cache-control header to expire in a coherent way 2019-10-15 12:48:50 +02:00
Daniel García Aubert
f8e117a7b7 JSHint is not ready for modern javascript 2019-10-15 11:46:44 +02:00
Daniel García Aubert
c4054f0ac9 Use develop branch of query-tables 2019-10-15 10:39:31 +02:00
Daniel García Aubert
f7707141d6 Rename variable 2019-10-08 17:22:24 +02:00
Daniel G. Aubert
c40c42fc10 Merge pull request #1130 from CartoDB/remove-routes-adapter
Remove environment configuration adapter
2019-10-08 16:34:24 +02:00
Daniel García Aubert
6cad976078 Remove environment configuration adapter 2019-10-08 11:02:32 +02:00
Daniel G. Aubert
c82f17e5d2 Merge pull request #1126 from CartoDB/gears
Be able to inject middlewares from configuration
2019-10-07 17:35:01 +02:00
Daniel G. Aubert
1054bde7fd Merge pull request #1127 from CartoDB/folders
Standardize folder structure and filenames
2019-10-07 17:34:27 +02:00
Daniel G. Aubert
9e23b91f3f Merge pull request #1129 from CartoDB/fix-routes-config
Convert from v1 to api in routes config
2019-10-07 17:34:00 +02:00
Daniel García Aubert
ea6e064e42 Convert from v1 to api in routes config 2019-10-07 14:08:59 +02:00
Raúl Marín
cf0858f5b9 Merge pull request #1128 from Algunenano/sec
Tests: Remove unnecessary extra qualification
2019-10-07 14:03:06 +02:00
Raul Marin
69b11a8412 sec 2019-10-07 13:36:18 +02:00
Daniel García Aubert
55aad4254c Remove cartodb folder in unit test 2019-10-07 11:29:07 +02:00
Daniel García Aubert
73e1659378 Add suffix '-test' to every test-suite file 2019-10-07 11:16:48 +02:00
Daniel García Aubert
98f3e8159e Stop using __dirname in requires 2019-10-07 10:55:26 +02:00
Daniel García Aubert
e8cff194fc Rename template_maps -> template-maps 2019-10-07 10:50:14 +02:00
Daniel García Aubert
f1de1b3b91 Rename test files: stop using underscores, use hyphens instead 2019-10-07 10:44:45 +02:00
Daniel García Aubert
a134ab3012 Rename server_options -> server-options 2019-10-07 10:10:51 +02:00
Daniel García Aubert
5a84d7233b Rename table_name_parser -> table-name-parser 2019-10-07 10:07:25 +02:00
Daniel García Aubert
8fe0112568 Rename overviews_query_rewriter -> overviews-query-rewriter 2019-10-07 10:06:01 +02:00
Daniel García Aubert
3acaac5403 Rename icu_data_env_setter -> icu-data-env-setter 2019-10-07 10:04:39 +02:00
Daniel García Aubert
7dbac5a565 Rename profiler_proxy -> profiler-proxy 2019-10-07 10:01:18 +02:00
Daniel García Aubert
8fb4f4063f Rename health_check -> health-check 2019-10-07 09:59:54 +02:00
Daniel García Aubert
808718fb26 Rename cdb_request -> cdb-request 2019-10-07 09:58:21 +02:00
Daniel García Aubert
6dc8de315a Rename surrogate_keys_cache -> surrogate-keys-cache 2019-10-07 09:56:20 +02:00
Daniel García Aubert
afb9b08925 Rename surrogate_keys_cache -> surrogate-keys-cache 2019-10-07 09:55:55 +02:00
Daniel García Aubert
2bed034e64 Rename named_map_provider_cache -> named-map-provider-cache 2019-10-07 09:54:54 +02:00
Daniel García Aubert
2328bb6261 Rename layergroup_affected_tables -> layergroup-affected-tables 2019-10-07 09:53:06 +02:00
Daniel García Aubert
06357fa3f9 Rename named_maps_entry -> named-maps-entry 2019-10-07 09:51:51 +02:00
Daniel García Aubert
83f58288f9 Rename varnish_http -> varnish-http 2019-10-07 09:47:42 +02:00
Daniel García Aubert
b1d5f0f9e8 Rename pg_query_runner -> pg-query-runner 2019-10-07 09:45:46 +02:00
Daniel García Aubert
7142e4db37 Rename pg_connection -> pg-connection 2019-10-07 09:43:40 +02:00
Daniel García Aubert
281a079a62 Simplify folder structure 2019-10-07 09:40:50 +02:00
Daniel García Aubert
0d638e6bad Fix command example 2019-10-06 19:12:11 +02:00
Daniel García Aubert
43a63feaca Keep the backwards compatibility for routing configuration 2019-10-06 18:58:21 +02:00
Daniel García Aubert
4aa6ffe28c Add tests to check custom middlewares behavior 2019-10-04 17:54:32 +02:00
Daniel García Aubert
2ce688ee2a Missed to apply configuration changes to default server options 2019-10-04 12:56:36 +02:00
Daniel García Aubert
4e967980a3 Prepare next release ans update news 2019-10-04 12:41:27 +02:00
Daniel García Aubert
93edf07da8 Temporary workaround to not depend on configuration changes 2019-10-04 12:35:12 +02:00
Daniel García Aubert
a684bead92 Rename method 'register' -> 'route' 2019-10-04 12:22:23 +02:00
Daniel García Aubert
dd06de2632 Use new routes configuration 2019-10-04 12:07:58 +02:00
Daniel García Aubert
975f07df99 Use Object.values() 2019-10-02 10:42:29 +02:00
Daniel García Aubert
5fe6845d7c Add comments 2019-10-01 19:48:16 +02:00
Daniel García Aubert
4aa844946d Update environment example files 2019-10-01 19:42:04 +02:00
Daniel García Aubert
3220e3de31 Remove old api configuration paths 2019-10-01 19:34:03 +02:00
Daniel García Aubert
26bba3c5f5 Prepare next release version 2019-10-01 19:31:14 +02:00
Daniel García Aubert
c82a5c38df Fix indentation 2019-10-01 18:20:17 +02:00
Daniel García Aubert
9cfaf6eefc Draft: be able to inject middlewares from configuration 2019-09-30 19:18:36 +02:00
275 changed files with 1373 additions and 875 deletions

17
NEWS.md
View File

@@ -1,5 +1,22 @@
# Changelog
## 8.0.0
Released 2019-11-13
Breaking changes:
- Schema change for "routes" in configuration file, each "router" is now an array instead of an object. See [`dd06de2`](https://github.com/CartoDB/Windshaft-cartodb/pull/1126/commits/dd06de2632661e19d64c9fbc2be0ba1a8059f54c) for more details.
Announcements:
- Added validation to only allow "count" and "sum" aggregations in dataview overview.
- Added mechanism to inject custom middlewares through configuration.
- Stop requiring unused config properties: "base_url", "base_url_mapconfig", and "base_url_templated".
- Upgraded cartodb-query-tables to version [0.7.0](https://github.com/CartoDB/node-cartodb-query-tables/blob/0.7.0/NEWS.md#version-0.7.0).
- Be able to set a coherent TTL in Cache-Control header to expire all resources belonging to a map simultaneously.
- When `cache buster` in request path is `0` set header `Last-Modified` to now, it avoids stalled content in 3rd party cache providers when they add `If-Modified-Since` header into the request.
- Adding a logger to MapStore (#1134)
- Qualify calls to cartodb extension so having it in the search_path isn't necessary.
- Fix multiple DB login issues.
## 7.2.0
Released 2019-09-30

View File

@@ -24,7 +24,7 @@ Create the config/environments/<env>.js files (there are .example files
to start from). You can optionally use the ./configure script for this,
see ```./configure --help``` to see available options.
Look at lib/cartodb/server_options.js for more on config
Look at lib/cartodb/server-options.js for more on config
Upgrading
---------

14
app.js
View File

@@ -6,7 +6,7 @@ var path = require('path');
var fs = require('fs');
var _ = require('underscore');
var semver = require('semver');
const setICUEnvVariable = require('./lib/cartodb/utils/icu_data_env_setter');
const setICUEnvVariable = require('./lib/utils/icu-data-env-setter');
// jshint undef:false
var log = console.log.bind(console);
@@ -24,12 +24,12 @@ if (!semver.satisfies(nodejsVersion, engines.node)) {
setICUEnvVariable();
var argv = require('yargs')
.usage('Usage: $0 <environment> [options]')
.usage('Usage: node $0 <environment> [options]')
.help('h')
.example(
'$0 production -c /etc/sql-api/config.js',
'start server in production environment with /etc/sql-api/config.js as config file'
)
'node $0 production -c /etc/windshaft-cartodb/config.js',
'start server in production environment with /etc/windshaft-cartodb/config.js as config file'
)
.alias('h', 'help')
.alias('c', 'config')
.nargs('c', 1)
@@ -105,8 +105,8 @@ global.logger = global.log4js.getLogger();
// Include cartodb_windshaft only _after_ the "global" variable is set
// See https://github.com/Vizzuality/Windshaft-cartodb/issues/28
var cartodbWindshaft = require('./lib/cartodb/server');
var serverOptions = require('./lib/cartodb/server_options');
var cartodbWindshaft = require('./lib/server');
var serverOptions = require('./lib/server-options');
var server = cartodbWindshaft(serverOptions);

View File

@@ -16,47 +16,41 @@ var config = {
// Base URLs for the APIs
//
// See https://github.com/CartoDB/Windshaft-cartodb/wiki/Unified-Map-API
//
// Note: each entry corresponds with an express' router.
// You must define at least one path. However, middlewares are optional.
,routes: {
v1: {
api: [{
paths: [
'/api/v1',
'/user/:user/api/v1',
],
// Base url for the Detached Maps API
// "/api/v1/map" is the new API,
map: {
paths: [
'/map',
]
},
// Base url for the Templated Maps API
// "/api/v1/map/named" is the new API,
template: {
paths: [
'/map/named'
]
}
},
// For compatibility with versions up to 1.6.x
v0: {
paths: [
'/tiles'
// Optional: attach middlewares at the begining of the router
// to perform custom operations.
middlewares: [
function noop () {
return function noopMiddleware (req, res, next) {
next();
}
}
],
// Base url for the Detached Maps API
// "/tiles/layergroup" is for compatibility with versions up to 1.6.x
map: {
// "/api/v1/map" is the new API,
map: [{
paths: [
'/layergroup'
]
},
'/map',
],
middlewares: [] // Optional
}],
// Base url for the Templated Maps API
// "/tiles/template" is for compatibility with versions up to 1.6.x
template: {
// "/api/v1/map/named" is the new API,
template: [{
paths: [
'/template'
]
}
}
'/map/named'
],
middlewares: [] // Optional
}]
}]
}
// Resource URLs expose endpoints to request/retrieve metadata associated to Maps: dataviews, analysis node status.
@@ -92,7 +86,8 @@ var config = {
// If log_filename is given logs will be written
// there, in append mode. Otherwise stdout is used (default).
// Log file will be re-opened on receiving the HUP signal
,log_filename: 'logs/node-windshaft.log'
,log_filename: undefined
,log_windshaft: true
// Templated database username for authorized user
// Supported labels: 'user_id' (read from redis)
,postgres_auth_user: 'development_cartodb_user_<%= user_id %>'
@@ -271,7 +266,7 @@ var config = {
// If filename is given logs comming from analysis client will be written
// there, in append mode. Otherwise 'log_filename' is used. Otherwise stdout is used (default).
// Log file will be re-opened on receiving the HUP signal
filename: 'logs/node-windshaft-analysis.log'
filename: undefined
},
// Define max execution time in ms for analyses or tags
// If analysis or tag are not found in redis this values will be used as default.

View File

@@ -16,47 +16,41 @@ var config = {
// Base URLs for the APIs
//
// See https://github.com/CartoDB/Windshaft-cartodb/wiki/Unified-Map-API
//
// Note: each entry corresponds with an express' router.
// You must define at least one path. However, middlewares are optional.
,routes: {
v1: {
api: [{
paths: [
'/api/v1',
'/user/:user/api/v1',
],
// Base url for the Detached Maps API
// "/api/v1/map" is the new API,
map: {
paths: [
'/map',
]
},
// Base url for the Templated Maps API
// "/api/v1/map/named" is the new API,
template: {
paths: [
'/map/named'
]
}
},
// For compatibility with versions up to 1.6.x
v0: {
paths: [
'/tiles'
// Optional: attach middlewares at the begining of the router
// to perform custom operations.
middlewares: [
function noop () {
return function noopMiddleware (req, res, next) {
next();
}
}
],
// Base url for the Detached Maps API
// "/tiles/layergroup" is for compatibility with versions up to 1.6.x
map: {
// "/api/v1/map" is the new API,
map: [{
paths: [
'/layergroup'
]
},
'/map',
],
middlewares: [] // Optional
}],
// Base url for the Templated Maps API
// "/tiles/template" is for compatibility with versions up to 1.6.x
template: {
// "/api/v1/map/named" is the new API,
template: [{
paths: [
'/template'
]
}
}
'/map/named'
],
middlewares: [] // Optional
}]
}]
}
// Resource URLs expose endpoints to request/retrieve metadata associated to Maps: dataviews, analysis node status.
@@ -93,6 +87,7 @@ var config = {
// there, in append mode. Otherwise stdout is used (default).
// Log file will be re-opened on receiving the HUP signal
,log_filename: 'logs/node-windshaft.log'
,log_windshaft: true
// Templated database username for authorized user
// Supported labels: 'user_id' (read from redis)
,postgres_auth_user: 'cartodb_user_<%= user_id %>'

View File

@@ -16,47 +16,41 @@ var config = {
// Base URLs for the APIs
//
// See https://github.com/CartoDB/Windshaft-cartodb/wiki/Unified-Map-API
//
// Note: each entry corresponds with an express' router.
// You must define at least one path. However, middlewares are optional.
,routes: {
v1: {
api: [{
paths: [
'/api/v1',
'/user/:user/api/v1',
],
// Base url for the Detached Maps API
// "/api/v1/map" is the new API,
map: {
paths: [
'/map',
]
},
// Base url for the Templated Maps API
// "/api/v1/map/named" is the new API,
template: {
paths: [
'/map/named'
]
}
},
// For compatibility with versions up to 1.6.x
v0: {
paths: [
'/tiles'
// Optional: attach middlewares at the begining of the router
// to perform custom operations.
middlewares: [
function noop () {
return function noopMiddleware (req, res, next) {
next();
}
}
],
// Base url for the Detached Maps API
// "/tiles/layergroup" is for compatibility with versions up to 1.6.x
map: {
// "/api/v1/map" is the new API,
map: [{
paths: [
'/layergroup'
]
},
'/map',
],
middlewares: [] // Optional
}],
// Base url for the Templated Maps API
// "/tiles/template" is for compatibility with versions up to 1.6.x
template: {
// "/api/v1/map/named" is the new API,
template: [{
paths: [
'/template'
]
}
}
'/map/named'
],
middlewares: [] // Optional
}]
}]
}
// Resource URLs expose endpoints to request/retrieve metadata associated to Maps: dataviews, analysis node status.
@@ -93,6 +87,7 @@ var config = {
// there, in append mode. Otherwise stdout is used (default).
// Log file will be re-opened on receiving the HUP signal
,log_filename: 'logs/node-windshaft.log'
,log_windshaft: true
// Templated database username for authorized user
// Supported labels: 'user_id' (read from redis)
,postgres_auth_user: 'cartodb_staging_user_<%= user_id %>'

View File

@@ -16,47 +16,41 @@ var config = {
// Base URLs for the APIs
//
// See https://github.com/CartoDB/Windshaft-cartodb/wiki/Unified-Map-API
//
// Note: each entry corresponds with an express' router.
// You must define at least one path. However, middlewares are optional.
,routes: {
v1: {
api: [{
paths: [
'/api/v1',
'/user/:user/api/v1',
],
// Base url for the Detached Maps API
// "/api/v1/map" is the new API,
map: {
paths: [
'/map',
]
},
// Base url for the Templated Maps API
// "/api/v1/map/named" is the new API,
template: {
paths: [
'/map/named'
]
}
},
// For compatibility with versions up to 1.6.x
v0: {
paths: [
'/tiles'
// Optional: attach middlewares at the begining of the router
// to perform custom operations.
middlewares: [
function noop () {
return function noopMiddleware (req, res, next) {
next();
}
}
],
// Base url for the Detached Maps API
// "/tiles/layergroup" is for compatibility with versions up to 1.6.x
map: {
// "/api/v1/map" is the new API,
map: [{
paths: [
'/layergroup'
]
},
'/map',
],
middlewares: [] // Optional
}],
// Base url for the Templated Maps API
// "/tiles/template" is for compatibility with versions up to 1.6.x
template: {
// "/api/v1/map/named" is the new API,
template: [{
paths: [
'/template'
]
}
}
'/map/named'
],
middlewares: [] // Optional
}]
}]
}
// Resource URLs expose endpoints to request/retrieve metadata associated to Maps: dataviews, analysis node status.
@@ -93,6 +87,7 @@ var config = {
// there, in append mode. Otherwise stdout is used (default).
// Log file will be re-opened on receiving the HUP signal
,log_filename: '/tmp/node-windshaft.log'
,log_windshaft: true
// Templated database username for authorized user
// Supported labels: 'user_id' (read from redis)
,postgres_auth_user: 'test_windshaft_cartodb_user_<%= user_id %>'

View File

@@ -7,12 +7,12 @@ const cartodbRedis = require('cartodb-redis');
const windshaft = require('windshaft');
const PgConnection = require('../backends/pg_connection');
const PgConnection = require('../backends/pg-connection');
const AnalysisBackend = require('../backends/analysis');
const AnalysisStatusBackend = require('../backends/analysis-status');
const DataviewBackend = require('../backends/dataview');
const TemplateMaps = require('../backends/template_maps.js');
const PgQueryRunner = require('../backends/pg_query_runner');
const TemplateMaps = require('../backends/template-maps');
const PgQueryRunner = require('../backends/pg-query-runner');
const StatsBackend = require('../backends/stats');
const AuthBackend = require('../backends/auth');
@@ -23,12 +23,12 @@ const TablesExtentBackend = require('../backends/tables-extent');
const ClusterBackend = require('../backends/cluster');
const LayergroupAffectedTablesCache = require('../cache/layergroup_affected_tables');
const SurrogateKeysCache = require('../cache/surrogate_keys_cache');
const VarnishHttpCacheBackend = require('../cache/backend/varnish_http');
const LayergroupAffectedTablesCache = require('../cache/layergroup-affected-tables');
const SurrogateKeysCache = require('../cache/surrogate-keys-cache');
const VarnishHttpCacheBackend = require('../cache/backend/varnish-http');
const FastlyCacheBackend = require('../cache/backend/fastly');
const NamedMapProviderCache = require('../cache/named_map_provider_cache');
const NamedMapsCacheEntry = require('../cache/model/named_maps_entry');
const NamedMapProviderCache = require('../cache/named-map-provider-cache');
const NamedMapsCacheEntry = require('../cache/model/named-maps-entry');
const NamedMapProviderReporter = require('../stats/reporter/named-map-provider');
const SqlWrapMapConfigAdapter = require('../models/mapconfig/adapter/sql-wrap-mapconfig-adapter');
@@ -83,9 +83,13 @@ module.exports = class ApiRouter {
const metadataBackend = cartodbRedis({ pool: redisPool });
const pgConnection = new PgConnection(metadataBackend);
const windshaftLogger = environmentOptions.log_windshaft && global.log4js ?
global.log4js.getLogger('[windshaft]') :
null;
const mapStore = new windshaft.storage.MapStore({
pool: redisPool,
expire_time: serverOptions.grainstore.default_layergroup_ttl
expire_time: serverOptions.grainstore.default_layergroup_ttl,
logger: windshaftLogger
});
const rendererFactory = createRendererFactory({ redisPool, serverOptions, environmentOptions });
@@ -196,16 +200,17 @@ module.exports = class ApiRouter {
this.templateRouter = new TemplateRouter({ collaborators });
}
register (app) {
route (app, routes) {
// FIXME: we need a better way to reset cache while running tests
if (process.env.NODE_ENV === 'test') {
app.layergroupAffectedTablesCache = this.layergroupAffectedTablesCache;
}
Object.keys(this.serverOptions.routes).forEach(apiVersion => {
const routes = this.serverOptions.routes[apiVersion];
routes.forEach(route => {
const apiRouter = router({ mergeParams: true });
const { paths, middlewares = [] } = route;
middlewares.forEach(middleware => apiRouter.use(middleware()));
apiRouter.use(logger(this.serverOptions));
apiRouter.use(initializeStatusCode());
@@ -219,16 +224,14 @@ module.exports = class ApiRouter {
apiRouter.use(cors());
apiRouter.use(user());
this.templateRouter.register(apiRouter, routes.template.paths);
this.mapRouter.register(apiRouter, routes.map.paths);
this.templateRouter.route(apiRouter, route.template);
this.mapRouter.route(apiRouter, route.map);
apiRouter.use(sendResponse());
apiRouter.use(syntaxError());
apiRouter.use(errorMiddleware());
const apiPaths = routes.paths;
apiPaths.forEach(path => app.use(path, apiRouter));
paths.forEach(path => app.use(path, apiRouter));
});
}
};
@@ -283,7 +286,7 @@ function createSurrogateKeysCacheBackends(serverOptions) {
return cacheBackends;
}
const timeoutErrorTilePath = __dirname + '/../../../assets/render-timeout-fallback.png';
const timeoutErrorTilePath = __dirname + '/../../assets/render-timeout-fallback.png';
const timeoutErrorTile = require('fs').readFileSync(timeoutErrorTilePath, {encoding: null});
function createRendererFactory ({ redisPool, serverOptions, environmentOptions }) {

View File

@@ -17,7 +17,7 @@ module.exports = class AnalysesController {
this.userLimitsBackend = userLimitsBackend;
}
register (mapRouter) {
route (mapRouter) {
mapRouter.get('/analyses/catalog', this.middlewares());
}

View File

@@ -17,7 +17,7 @@ module.exports = class AnalysisLayergroupController {
this.authBackend = authBackend;
}
register (mapRouter) {
route (mapRouter) {
mapRouter.get('/:token/analysis/node/:nodeId', this.middlewares());
}

View File

@@ -64,7 +64,7 @@ module.exports = class AnonymousMapController {
this.layergroupMetadata = layergroupMetadata;
}
register (mapRouter) {
route (mapRouter) {
mapRouter.options('/');
mapRouter.get('/', this.middlewares());
mapRouter.post('/', this.middlewares());

View File

@@ -32,7 +32,7 @@ module.exports = class AttributesLayergroupController {
this.surrogateKeysCache = surrogateKeysCache;
}
register (mapRouter) {
route (mapRouter) {
mapRouter.get('/:token/:layer/attributes/:fid', this.middlewares());
}

View File

@@ -32,7 +32,7 @@ module.exports = class AggregatedFeaturesLayergroupController {
this.surrogateKeysCache = surrogateKeysCache;
}
register (mapRouter) {
route (mapRouter) {
mapRouter.get('/:token/:layer/:z/cluster/:clusterId', this.middlewares());
}

View File

@@ -47,7 +47,7 @@ module.exports = class DataviewLayergroupController {
this.surrogateKeysCache = surrogateKeysCache;
}
register (mapRouter) {
route (mapRouter) {
// Undocumented/non-supported API endpoint methods.
// Use at your own peril.

View File

@@ -126,19 +126,25 @@ module.exports = class MapRouter {
);
}
register (apiRouter, mapPaths) {
route (apiRouter, routes) {
const mapRouter = router({ mergeParams: true });
this.analysisLayergroupController.register(mapRouter);
this.attributesLayergroupController.register(mapRouter);
this.dataviewLayergroupController.register(mapRouter);
this.previewLayergroupController.register(mapRouter);
this.tileLayergroupController.register(mapRouter);
this.anonymousMapController.register(mapRouter);
this.previewTemplateController.register(mapRouter);
this.analysesController.register(mapRouter);
this.clusteredFeaturesLayergroupController.register(mapRouter);
routes.forEach(route => {
const { paths, middlewares = [] } = route;
mapPaths.forEach(path => apiRouter.use(path, mapRouter));
middlewares.forEach(middleware => mapRouter.use(middleware()));
this.analysisLayergroupController.route(mapRouter);
this.attributesLayergroupController.route(mapRouter);
this.dataviewLayergroupController.route(mapRouter);
this.previewLayergroupController.route(mapRouter);
this.tileLayergroupController.route(mapRouter);
this.anonymousMapController.route(mapRouter);
this.previewTemplateController.route(mapRouter);
this.analysesController.route(mapRouter);
this.clusteredFeaturesLayergroupController.route(mapRouter);
paths.forEach(path => apiRouter.use(path, mapRouter));
});
}
};

View File

@@ -35,7 +35,7 @@ module.exports = class PreviewLayergroupController {
this.surrogateKeysCache = surrogateKeysCache;
}
register (mapRouter) {
route (mapRouter) {
mapRouter.get('/static/center/:token/:z/:lat/:lng/:width/:height.:format', this.middlewares({
validateZoom: true,
previewType: 'centered'

View File

@@ -46,7 +46,7 @@ module.exports = class PreviewTemplateController {
this.userLimitsBackend = userLimitsBackend;
}
register (mapRouter) {
route (mapRouter) {
mapRouter.get('/static/named/:template_id/:width/:height.:format', this.middlewares());
}

View File

@@ -43,7 +43,7 @@ module.exports = class TileLayergroupController {
this.surrogateKeysCache = surrogateKeysCache;
}
register (mapRouter) {
route (mapRouter) {
// REGEXP: doesn't match with `val`
const not = (val) => `(?!${val})([^\/]+?)`;

View File

@@ -1,14 +1,40 @@
'use strict';
const ONE_YEAR_IN_SECONDS = 60 * 60 * 24 * 365;
const FIVE_MINUTES_IN_SECONDS = 60 * 5;
const ONE_MINUTE_IN_SECONDS = 60;
const THREE_MINUTE_IN_SECONDS = 60 * 3;
const FIVE_MINUTES_IN_SECONDS = ONE_MINUTE_IN_SECONDS * 5;
const TEN_MINUTES_IN_SECONDS = ONE_MINUTE_IN_SECONDS * 10;
const FIFTEEN_MINUTES_IN_SECONDS = ONE_MINUTE_IN_SECONDS * 15;
const THIRTY_MINUTES_IN_SECONDS = ONE_MINUTE_IN_SECONDS * 30;
const ONE_HOUR_IN_SECONDS = ONE_MINUTE_IN_SECONDS * 60;
const ONE_YEAR_IN_SECONDS = ONE_HOUR_IN_SECONDS * 24 * 365;
const FALLBACK_TTL = global.environment.varnish.fallbackTtl || FIVE_MINUTES_IN_SECONDS;
const validFallbackTTL = [
ONE_MINUTE_IN_SECONDS,
THREE_MINUTE_IN_SECONDS,
FIVE_MINUTES_IN_SECONDS,
TEN_MINUTES_IN_SECONDS,
FIFTEEN_MINUTES_IN_SECONDS,
THIRTY_MINUTES_IN_SECONDS,
ONE_HOUR_IN_SECONDS
];
module.exports = function setCacheControlHeader ({
ttl = ONE_YEAR_IN_SECONDS,
fallbackTtl = FALLBACK_TTL,
revalidate = false
} = {}) {
if (!validFallbackTTL.includes(fallbackTtl)) {
const message = [
'Invalid fallback TTL value for Cache-Control header.',
`Got ${fallbackTtl}, expected ${validFallbackTTL.join(', ')}`
].join(' ');
throw new Error(message);
}
return function setCacheControlHeaderMiddleware (req, res, next) {
if (req.method !== 'GET') {
return next();
@@ -27,7 +53,7 @@ module.exports = function setCacheControlHeader ({
if (everyAffectedTableCanBeInvalidated(affectedTables)) {
directives.push(`max-age=${ttl}`);
} else {
directives.push(`max-age=${fallbackTtl}`);
directives.push(`max-age=${computeNextTTL({ ttlInSeconds: fallbackTtl })}`);
}
if (revalidate) {
@@ -49,3 +75,11 @@ function everyAffectedTableCanBeInvalidated (affectedTables) {
affectedTables.getTables(skipNotUpdatedAtTables, skipAnalysisCachedTables)
.every(table => table.updated_at !== null);
}
function computeNextTTL ({ ttlInSeconds } = {}) {
const nowInSeconds = Math.ceil(Date.now() / 1000);
const secondsAfterPreviousTTLStep = nowInSeconds % ttlInSeconds;
const secondsToReachTheNextTTLStep = ttlInSeconds - secondsAfterPreviousTTLStep;
return secondsToReachTheNextTTLStep;
}

View File

@@ -10,7 +10,9 @@ module.exports = function setLastModifiedHeader () {
if (cache_buster) {
const cacheBuster = parseInt(cache_buster, 10);
const lastModifiedDate = Number.isFinite(cacheBuster) ? new Date(cacheBuster) : new Date();
const lastModifiedDate = Number.isFinite(cacheBuster) && cacheBuster !== 0 ?
new Date(cacheBuster) :
new Date();
res.set('Last-Modified', lastModifiedDate.toUTCString());

View File

@@ -1,6 +1,6 @@
'use strict';
const Profiler = require('../../stats/profiler_proxy');
const Profiler = require('../../stats/profiler-proxy');
const debug = require('debug')('windshaft:cartodb:stats');
const onHeaders = require('on-headers');

View File

@@ -1,6 +1,6 @@
'use strict';
const NamedMapsCacheEntry = require('../../cache/model/named_maps_entry');
const NamedMapsCacheEntry = require('../../cache/model/named-maps-entry');
const NamedMapMapConfigProvider = require('../../models/mapconfig/provider/named-map-provider');
module.exports = function setSurrogateKeyHeader ({ surrogateKeysCache }) {

View File

@@ -1,6 +1,6 @@
'use strict';
const CdbRequest = require('../../models/cdb_request');
const CdbRequest = require('../../models/cdb-request');
module.exports = function user () {
const cdbRequest = new CdbRequest();

View File

@@ -1,7 +1,7 @@
'use strict';
const fs = require('fs');
const timeoutErrorVectorTile = fs.readFileSync(__dirname + '/../../../../assets/render-timeout-fallback.mvt');
const timeoutErrorVectorTile = fs.readFileSync(__dirname + '/../../../assets/render-timeout-fallback.mvt');
module.exports = function vectorError() {
return function vectorErrorMiddleware(err, req, res, next) {

View File

@@ -1,6 +1,6 @@
'use strict';
const { templateName } = require('../../backends/template_maps');
const { templateName } = require('../../backends/template-maps');
const credentials = require('../middlewares/credentials');
const rateLimit = require('../middlewares/rate-limit');
const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit;
@@ -18,7 +18,7 @@ module.exports = class AdminTemplateController {
this.userLimitsBackend = userLimitsBackend;
}
register (templateRouter) {
route (templateRouter) {
templateRouter.options(`/:template_id`);
templateRouter.post('/', this.middlewares({

View File

@@ -63,7 +63,7 @@ module.exports = class NamedMapController {
this.layergroupMetadata = layergroupMetadata;
}
register (templateRouter) {
route (templateRouter) {
templateRouter.get('/:template_id/jsonp', this.middlewares());
templateRouter.post('/:template_id', this.middlewares());
}

View File

@@ -54,13 +54,19 @@ module.exports = class TemplateRouter {
);
}
register (apiRouter, templatePaths) {
route (apiRouter, routes) {
const templateRouter = router({ mergeParams: true });
this.namedMapController.register(templateRouter);
this.tileTemplateController.register(templateRouter);
this.adminTemplateController.register(templateRouter);
routes.forEach(route => {
const { paths, middlewares = [] } = route;
templatePaths.forEach(path => apiRouter.use(path, templateRouter));
middlewares.forEach(middleware => templateRouter.use(middleware()));
this.namedMapController.route(templateRouter);
this.tileTemplateController.route(templateRouter);
this.adminTemplateController.route(templateRouter);
paths.forEach(path => apiRouter.use(path, templateRouter));
});
}
};

View File

@@ -31,7 +31,7 @@ module.exports = class TileTemplateController {
this.userLimitsBackend = userLimitsBackend;
}
register (templateRouter) {
route (templateRouter) {
templateRouter.get('/:template_id/:layer/:z/:x/:y.(:format)', this.middlewares());
}

View File

@@ -6,9 +6,9 @@ var BBoxFilter = require('../models/filter/bbox');
var DataviewFactory = require('../models/dataview/factory');
var DataviewFactoryWithOverviews = require('../models/dataview/overviews/factory');
const dbParamsFromReqParams = require('../utils/database-params');
var OverviewsQueryRewriter = require('../utils/overviews_query_rewriter');
var OverviewsQueryRewriter = require('../utils/overviews-query-rewriter');
var overviewsQueryRewriter = new OverviewsQueryRewriter({
zoom_level: 'CDB_ZoomFromScale(!scale_denominator!)'
zoom_level: 'cartodb.CDB_ZoomFromScale(!scale_denominator!)'
});
var dot = require('dot');

View File

@@ -12,9 +12,9 @@ OverviewsMetadataBackend.prototype.getOverviewsMetadata = function (username, sq
// FIXME: Currently using internal function _cdb_schema_name
// CDB_Overviews should provide the schema information directly.
const query = `
SELECT *, _cdb_schema_name(base_table)
FROM CDB_Overviews(
CDB_QueryTablesText($windshaft$${queryUtils.substituteDummyTokens(sql)}$windshaft$)
SELECT *, cartodb._cdb_schema_name(base_table)
FROM cartodb.CDB_Overviews(
cartodb.CDB_QueryTablesText($windshaft$${queryUtils.substituteDummyTokens(sql)}$windshaft$)
);
`;
this.pgQueryRunner.run(username, query, function handleOverviewsRows(err, rows) {

View File

@@ -3,6 +3,7 @@
var PSQL = require('cartodb-psql');
var _ = require('underscore');
const debug = require('debug')('cachechan');
const dbParamsFromReqParams = require('../utils/database-params');
function PgConnection(metadataBackend) {
this.metadataBackend = metadataBackend;
@@ -124,14 +125,7 @@ PgConnection.prototype.getConnection = function(username, callback) {
if (err) {
return callback(err);
}
return callback(err, new PSQL({
user: databaseParams.dbuser,
pass: databaseParams.dbpass,
host: databaseParams.dbhost,
port: databaseParams.dbport,
dbname: databaseParams.dbname
}));
return callback(err, new PSQL(dbParamsFromReqParams(databaseParams)));
});
};

View File

@@ -1,6 +1,7 @@
'use strict';
var PSQL = require('cartodb-psql');
const dbParamsFromReqParams = require('../utils/database-params');
function PgQueryRunner(pgConnection) {
this.pgConnection = pgConnection;
@@ -22,13 +23,7 @@ PgQueryRunner.prototype.run = function(username, query, callback) {
return callback(err);
}
const psql = new PSQL({
user: databaseParams.dbuser,
pass: databaseParams.dbpass,
host: databaseParams.dbhost,
port: databaseParams.dbport,
dbname: databaseParams.dbname
});
const psql = new PSQL(dbParamsFromReqParams(databaseParams));
psql.query(query, function (err, resultSet) {
resultSet = resultSet || {};

View File

@@ -3,7 +3,7 @@
const LruCache = require('lru-cache');
const NamedMapMapConfigProvider = require('../models/mapconfig/provider/named-map-provider');
const { templateName } = require('../backends/template_maps');
const { templateName } = require('../backends/template-maps');
const TEN_MINUTES_IN_MILLISECONDS = 1000 * 60 * 10;
const ACTIONS = ['update', 'delete'];

View File

@@ -1,6 +1,6 @@
'use strict';
const dataviews = require('./');
const dataviews = require('.');
module.exports = class DataviewFactory {
static get dataviews() {

View File

@@ -94,6 +94,8 @@ var CATEGORIES_LIMIT = 6;
function Aggregation(query, options, queryRewriter, queryRewriteData, params, queries) {
BaseOverviewsDataview.call(this, query, options, BaseDataview, queryRewriter, queryRewriteData, params, queries);
this._checkOptions(options);
this.query = query;
this.queries = queries;
this.column = options.column;
@@ -219,6 +221,26 @@ var aggregationFnQueryTpl = {
sum: dot.template('sum({{=it._aggregationColumn}}*_feature_count)')
};
const VALID_OPERATIONS = {
count: [],
sum: ['aggregationColumn']
};
Aggregation.prototype._checkOptions = function (options) {
if (!VALID_OPERATIONS[options.aggregation]) {
throw new Error(`Aggregation does not support '${options.aggregation}' operation in dataview overview options`);
}
const requiredOptions = VALID_OPERATIONS[options.aggregation];
const missingOptions = requiredOptions.filter(requiredOption => !options.hasOwnProperty(requiredOption));
if (missingOptions.length > 0) {
throw new Error(
`Aggregation '${options.aggregation}' is missing some options for overview: ${missingOptions.join(',')}`
);
}
};
Aggregation.prototype.getAggregationSql = function() {
return aggregationFnQueryTpl[this.aggregation]({
_aggregationFn: this.aggregation,

View File

@@ -1,7 +1,7 @@
'use strict';
var parentFactory = require('../factory');
var dataviews = require('./');
var dataviews = require('.');
function OverviewsDataviewFactory(queryRewriter, queryRewriteData, options) {
this.queryRewriter = queryRewriter;

Some files were not shown because too many files have changed in this diff Show More