diff --git a/config/environments/development.js.example b/config/environments/development.js.example index 842f55d2..f9c58abb 100644 --- a/config/environments/development.js.example +++ b/config/environments/development.js.example @@ -13,6 +13,8 @@ var config = { // from hostname. Must have a single grabbing block. ,user_from_host: '^(.*)\\.localhost' + // DEPRECATED: use routes property instead + // --------------------------------------- // Base URLs for the APIs // // See http://github.com/CartoDB/Windshaft-cartodb/wiki/Unified-Map-API @@ -26,6 +28,52 @@ var config = { // "tiles/layergroup" is for compatibility with versions up to 1.6.x ,base_url_detached: '(?:/api/v1/map|/user/:user/api/v1/map|/tiles/layergroup)' + // Base URLs for the APIs + // + // See https://github.com/CartoDB/Windshaft-cartodb/wiki/Unified-Map-API + ,routes: { + v1: { + 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' + ], + // Base url for the Detached Maps API + // "/tiles/layergroup" is for compatibility with versions up to 1.6.x + map: { + paths: [ + '/layergroup' + ] + }, + // Base url for the Templated Maps API + // "/tiles/template" is for compatibility with versions up to 1.6.x + template: { + paths: [ + '/template' + ] + } + } + } + // Resource URLs expose endpoints to request/retrieve metadata associated to Maps: dataviews, analysis node status. // // This URLs depend on how `base_url_detached` and `user_from_host` are configured: the application can be diff --git a/config/environments/production.js.example b/config/environments/production.js.example index 771ed2b5..89c5e5bd 100644 --- a/config/environments/production.js.example +++ b/config/environments/production.js.example @@ -13,6 +13,8 @@ var config = { // from hostname. Must have a single grabbing block. ,user_from_host: '^(.*)\\.cartodb\\.com$' + // DEPRECATED: use routes property instead + // --------------------------------------- // Base URLs for the APIs // // See http://github.com/CartoDB/Windshaft-cartodb/wiki/Unified-Map-API @@ -26,6 +28,52 @@ var config = { // "tiles/layergroup" is for compatibility with versions up to 1.6.x ,base_url_detached: '(?:/api/v1/map|/user/:user/api/v1/map|/tiles/layergroup)' + // Base URLs for the APIs + // + // See https://github.com/CartoDB/Windshaft-cartodb/wiki/Unified-Map-API + ,routes: { + v1: { + 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' + ], + // Base url for the Detached Maps API + // "/tiles/layergroup" is for compatibility with versions up to 1.6.x + map: { + paths: [ + '/layergroup' + ] + }, + // Base url for the Templated Maps API + // "/tiles/template" is for compatibility with versions up to 1.6.x + template: { + paths: [ + '/template' + ] + } + } + } + // Resource URLs expose endpoints to request/retrieve metadata associated to Maps: dataviews, analysis node status. // // This URLs depend on how `base_url_detached` and `user_from_host` are configured: the application can be diff --git a/config/environments/staging.js.example b/config/environments/staging.js.example index dd2d892c..76353f9b 100644 --- a/config/environments/staging.js.example +++ b/config/environments/staging.js.example @@ -13,6 +13,8 @@ var config = { // from hostname. Must have a single grabbing block. ,user_from_host: '^(.*)\\.cartodb\\.com$' + // DEPRECATED: use routes property instead + // --------------------------------------- // Base URLs for the APIs // // See http://github.com/CartoDB/Windshaft-cartodb/wiki/Unified-Map-API @@ -26,6 +28,52 @@ var config = { // "/tiles/layergroup" is for compatibility with versions up to 1.6.x ,base_url_detached: '(?:/api/v1/map|/user/:user/api/v1/map|/tiles/layergroup)' + // Base URLs for the APIs + // + // See https://github.com/CartoDB/Windshaft-cartodb/wiki/Unified-Map-API + ,routes: { + v1: { + 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' + ], + // Base url for the Detached Maps API + // "/tiles/layergroup" is for compatibility with versions up to 1.6.x + map: { + paths: [ + '/layergroup' + ] + }, + // Base url for the Templated Maps API + // "/tiles/template" is for compatibility with versions up to 1.6.x + template: { + paths: [ + '/template' + ] + } + } + } + // Resource URLs expose endpoints to request/retrieve metadata associated to Maps: dataviews, analysis node status. // // This URLs depend on how `base_url_detached` and `user_from_host` are configured: the application can be diff --git a/config/environments/test.js.example b/config/environments/test.js.example index 4d2c2d27..1f4e34a6 100644 --- a/config/environments/test.js.example +++ b/config/environments/test.js.example @@ -13,6 +13,8 @@ var config = { // from hostname. Must have a single grabbing block. ,user_from_host: '(.*)' + // DEPRECATED: use routes property instead + // --------------------------------------- // Base URLs for the APIs // // See https://github.com/CartoDB/Windshaft-cartodb/wiki/Unified-Map-API @@ -26,6 +28,52 @@ var config = { // "tiles/layergroup" is for compatibility with versions up to 1.6.x ,base_url_detached: '(?:/api/v1/map|/user/:user/api/v1/map|/tiles/layergroup)' + // Base URLs for the APIs + // + // See https://github.com/CartoDB/Windshaft-cartodb/wiki/Unified-Map-API + ,routes: { + v1: { + 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' + ], + // Base url for the Detached Maps API + // "/tiles/layergroup" is for compatibility with versions up to 1.6.x + map: { + paths: [ + '/layergroup' + ] + }, + // Base url for the Templated Maps API + // "/tiles/template" is for compatibility with versions up to 1.6.x + template: { + paths: [ + '/template' + ] + } + } + } + // Resource URLs expose endpoints to request/retrieve metadata associated to Maps: dataviews, analysis node status. // // This URLs depend on how `base_url_detached` and `user_from_host` are configured: the application can be diff --git a/lib/cartodb/controllers/api-router.js b/lib/cartodb/api/api-router.js similarity index 80% rename from lib/cartodb/controllers/api-router.js rename to lib/cartodb/api/api-router.js index d7d34837..9d53285b 100644 --- a/lib/cartodb/controllers/api-router.js +++ b/lib/cartodb/api/api-router.js @@ -12,12 +12,12 @@ const DataviewBackend = require('../backends/dataview'); const TemplateMaps = require('../backends/template_maps.js'); const PgQueryRunner = require('../backends/pg_query_runner'); const StatsBackend = require('../backends/stats'); +const AuthBackend = require('../backends/auth'); -const AuthApi = require('../api/auth_api'); -const UserLimitsApi = require('../api/user_limits_api'); -const OverviewsMetadataApi = require('../api/overviews_metadata_api'); -const FilterStatsApi = require('../api/filter_stats_api'); -const TablesExtentApi = require('../api/tables_extent_api'); +const UserLimitsBackend = require('../backends/user-limits'); +const OverviewsMetadataBackend = require('../backends/overviews-metadata'); +const FilterStatsApi = require('../backends/filter-stats'); +const TablesExtentBackend = require('../backends/tables-extent'); const LayergroupAffectedTablesCache = require('../cache/layergroup_affected_tables'); const SurrogateKeysCache = require('../cache/surrogate_keys_cache'); @@ -40,19 +40,20 @@ const ResourceLocator = require('../models/resource-locator'); const LayergroupMetadata = require('../utils/layergroup-metadata'); const RendererStatsReporter = require('../stats/reporter/renderer'); -const logger = require('../middleware/logger'); +const initializeStatusCode = require('./middlewares/initialize-status-code'); +const logger = require('./middlewares/logger'); const bodyParser = require('body-parser'); -const servedByHostHeader = require('../middleware/served-by-host-header'); -const stats = require('../middleware/stats'); -const lzmaMiddleware = require('../middleware/lzma'); -const cors = require('../middleware/cors'); -const user = require('../middleware/user'); -const sendResponse = require('../middleware/send-response'); -const syntaxError = require('../middleware/syntax-error'); -const errorMiddleware = require('../middleware/error-middleware'); +const servedByHostHeader = require('./middlewares/served-by-host-header'); +const stats = require('./middlewares/stats'); +const lzmaMiddleware = require('./middlewares/lzma'); +const cors = require('./middlewares/cors'); +const user = require('./middlewares/user'); +const sendResponse = require('./middlewares/send-response'); +const syntaxError = require('./middlewares/syntax-error'); +const errorMiddleware = require('./middlewares/error-middleware'); -const MapRouter = require('./map-router'); -const TemplateRouter = require('./template-router'); +const MapRouter = require('./map/map-router'); +const TemplateRouter = require('./template/template-router'); module.exports = class ApiRouter { constructor ({ serverOptions, environmentOptions }) { @@ -107,14 +108,14 @@ module.exports = class ApiRouter { const dataviewBackend = new DataviewBackend(analysisBackend); const statsBackend = new StatsBackend(); - const userLimitsApi = new UserLimitsApi(metadataBackend, { + const userLimitsBackend = new UserLimitsBackend(metadataBackend, { limits: { cacheOnTimeout: serverOptions.renderer.mapnik.limits.cacheOnTimeout || false, render: serverOptions.renderer.mapnik.limits.render || 0, rateLimitsEnabled: global.environment.enabledFeatures.rateLimitsEnabled } }); - const authApi = new AuthApi(pgConnection, metadataBackend, mapStore, templateMaps); + const authBackend = new AuthBackend(pgConnection, metadataBackend, mapStore, templateMaps); const layergroupAffectedTablesCache = new LayergroupAffectedTablesCache(); @@ -123,10 +124,10 @@ module.exports = class ApiRouter { } const pgQueryRunner = new PgQueryRunner(pgConnection); - const overviewsMetadataApi = new OverviewsMetadataApi(pgQueryRunner); + const overviewsMetadataBackend = new OverviewsMetadataBackend(pgQueryRunner); - const filterStatsApi = new FilterStatsApi(pgQueryRunner); - const tablesExtentApi = new TablesExtentApi(pgQueryRunner); + const filterStatsBackend = new FilterStatsApi(pgQueryRunner); + const tablesExtentBackend = new TablesExtentBackend(pgQueryRunner); const mapConfigAdapter = new MapConfigAdapter( new MapConfigNamedLayersAdapter(templateMaps, pgConnection), @@ -135,7 +136,7 @@ module.exports = class ApiRouter { new DataviewsWidgetsAdapter(), new AnalysisMapConfigAdapter(analysisBackend), new AggregationMapConfigAdapter(pgConnection), - new MapConfigOverviewsAdapter(overviewsMetadataApi, filterStatsApi), + new MapConfigOverviewsAdapter(overviewsMetadataBackend, filterStatsBackend), new TurboCartoAdapter() ); @@ -146,7 +147,7 @@ module.exports = class ApiRouter { templateMaps, pgConnection, metadataBackend, - userLimitsApi, + userLimitsBackend, mapConfigAdapter, layergroupAffectedTablesCache ); @@ -163,9 +164,9 @@ module.exports = class ApiRouter { tileBackend, pgConnection, mapStore, - userLimitsApi, + userLimitsBackend, layergroupAffectedTablesCache, - authApi, + authBackend, surrogateKeysCache, templateMaps, mapBackend, @@ -174,7 +175,7 @@ module.exports = class ApiRouter { statsBackend, layergroupMetadata, namedMapProviderCache, - tablesExtentApi + tablesExtentBackend }; this.mapRouter = new MapRouter({ collaborators }); @@ -187,34 +188,34 @@ module.exports = class ApiRouter { app.layergroupAffectedTablesCache = this.layergroupAffectedTablesCache; } - const apiRouter = router(); + Object.keys(this.serverOptions.routes).forEach(apiVersion => { + const routes = this.serverOptions.routes[apiVersion]; - apiRouter.use(logger(this.serverOptions)); - apiRouter.use(bodyParser.json()); - apiRouter.use(servedByHostHeader()); - apiRouter.use(stats({ - enabled: this.serverOptions.useProfiler, - statsClient: global.statsClient - })); - apiRouter.use(lzmaMiddleware()); - apiRouter.use(cors()); - apiRouter.use(user()); + const apiRouter = router(); - this.templateRouter.register(apiRouter); - this.mapRouter.register(apiRouter); + apiRouter.use(logger(this.serverOptions)); + apiRouter.use(initializeStatusCode()); + apiRouter.use(bodyParser.json()); + apiRouter.use(servedByHostHeader()); + apiRouter.use(stats({ + enabled: this.serverOptions.useProfiler, + statsClient: global.statsClient + })); + apiRouter.use(lzmaMiddleware()); + apiRouter.use(cors()); + apiRouter.use(user()); - apiRouter.use(sendResponse()); - apiRouter.use(syntaxError()); - apiRouter.use(errorMiddleware()); + this.templateRouter.register(apiRouter, routes.template.paths); + this.mapRouter.register(apiRouter, routes.map.paths); - const paths = [ - '/api/v1', - '/user/:user/api/v1', - '/tiles', // Deprecated - '/database/:dbname' // Deprecated: used in ported test from windshaft - ]; + apiRouter.use(sendResponse()); + apiRouter.use(syntaxError()); + apiRouter.use(errorMiddleware()); - app.use(`(?:${paths.join('|')})`, apiRouter); + const apiPaths = routes.paths; + + apiPaths.forEach(path => app.use(path, apiRouter)); + }); } }; diff --git a/lib/cartodb/controllers/analyses.js b/lib/cartodb/api/map/analyses-catalog-controller.js similarity index 83% rename from lib/cartodb/controllers/analyses.js rename to lib/cartodb/api/map/analyses-catalog-controller.js index cc6dd3a6..760c0e80 100644 --- a/lib/cartodb/controllers/analyses.js +++ b/lib/cartodb/api/map/analyses-catalog-controller.js @@ -1,17 +1,17 @@ const PSQL = require('cartodb-psql'); -const cleanUpQueryParams = require('../middleware/clean-up-query-params'); -const credentials = require('../middleware/credentials'); -const authorize = require('../middleware/authorize'); -const dbConnSetup = require('../middleware/db-conn-setup'); -const rateLimit = require('../middleware/rate-limit'); +const cleanUpQueryParams = require('../middlewares/clean-up-query-params'); +const credentials = require('../middlewares/credentials'); +const authorize = require('../middlewares/authorize'); +const dbConnSetup = require('../middlewares/db-conn-setup'); +const rateLimit = require('../middlewares/rate-limit'); const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit; -const cacheControlHeader = require('../middleware/cache-control-header'); -const dbParamsFromResLocals = require('../utils/database-params'); +const cacheControlHeader = require('../middlewares/cache-control-header'); +const dbParamsFromResLocals = require('../../utils/database-params'); -function AnalysesController(pgConnection, authApi, userLimitsApi) { +function AnalysesController(pgConnection, authBackend, userLimitsBackend) { this.pgConnection = pgConnection; - this.authApi = authApi; - this.userLimitsApi = userLimitsApi; + this.authBackend = authBackend; + this.userLimitsBackend = userLimitsBackend; } module.exports = AnalysesController; @@ -20,9 +20,9 @@ AnalysesController.prototype.register = function (mapRouter) { mapRouter.get( `/analyses/catalog`, credentials(), - authorize(this.authApi), + authorize(this.authBackend), dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.ANALYSIS_CATALOG), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.ANALYSIS_CATALOG), cleanUpQueryParams(), createPGClient(), getDataFromQuery({ queryTemplate: catalogQueryTpl, key: 'catalog' }), @@ -99,6 +99,7 @@ function prepareResponse () { return -1; }); + res.statusCode = 200; res.body = { catalog: analysisCatalog }; next(); diff --git a/lib/cartodb/controllers/layergroup/analysis.js b/lib/cartodb/api/map/analysis-layergroup-controller.js similarity index 57% rename from lib/cartodb/controllers/layergroup/analysis.js rename to lib/cartodb/api/map/analysis-layergroup-controller.js index 36f20991..96f46d70 100644 --- a/lib/cartodb/controllers/layergroup/analysis.js +++ b/lib/cartodb/api/map/analysis-layergroup-controller.js @@ -1,29 +1,18 @@ -const layergroupToken = require('../../middleware/layergroup-token'); -const cleanUpQueryParams = require('../../middleware/clean-up-query-params'); -const credentials = require('../../middleware/credentials'); -const dbConnSetup = require('../../middleware/db-conn-setup'); -const authorize = require('../../middleware/authorize'); -const rateLimit = require('../../middleware/rate-limit'); +const layergroupToken = require('../middlewares/layergroup-token'); +const cleanUpQueryParams = require('../middlewares/clean-up-query-params'); +const credentials = require('../middlewares/credentials'); +const dbConnSetup = require('../middlewares/db-conn-setup'); +const authorize = require('../middlewares/authorize'); +const rateLimit = require('../middlewares/rate-limit'); const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit; const dbParamsFromResLocals = require('../../utils/database-params'); module.exports = class AnalysisLayergroupController { - constructor ( - analysisStatusBackend, - pgConnection, - mapStore, - userLimitsApi, - layergroupAffectedTablesCache, - authApi, - surrogateKeysCache - ) { + constructor (analysisStatusBackend, pgConnection, userLimitsBackend, authBackend) { this.analysisStatusBackend = analysisStatusBackend; this.pgConnection = pgConnection; - this.mapStore = mapStore; - this.userLimitsApi = userLimitsApi; - this.layergroupAffectedTablesCache = layergroupAffectedTablesCache; - this.authApi = authApi; - this.surrogateKeysCache = surrogateKeysCache; + this.userLimitsBackend = userLimitsBackend; + this.authBackend = authBackend; } register (mapRouter) { @@ -31,9 +20,9 @@ module.exports = class AnalysisLayergroupController { `/:token/analysis/node/:nodeId`, layergroupToken(), credentials(), - authorize(this.authApi), + authorize(this.authBackend), dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.ANALYSIS), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.ANALYSIS), cleanUpQueryParams(), analysisNodeStatus(this.analysisStatusBackend) ); @@ -59,6 +48,7 @@ function analysisNodeStatus (analysisStatusBackend) { 'Last-Modified': new Date().toUTCString() }); + res.statusCode = 200; res.body = nodeStatus; next(); diff --git a/lib/cartodb/controllers/map/anonymous.js b/lib/cartodb/api/map/anonymous-map-controller.js similarity index 76% rename from lib/cartodb/controllers/map/anonymous.js rename to lib/cartodb/api/map/anonymous-map-controller.js index 433da3e4..21049437 100644 --- a/lib/cartodb/controllers/map/anonymous.js +++ b/lib/cartodb/api/map/anonymous-map-controller.js @@ -1,35 +1,35 @@ const windshaft = require('windshaft'); const MapConfig = windshaft.model.MapConfig; const Datasource = windshaft.model.Datasource; -const cleanUpQueryParams = require('../../middleware/clean-up-query-params'); -const credentials = require('../../middleware/credentials'); -const dbConnSetup = require('../../middleware/db-conn-setup'); -const authorize = require('../../middleware/authorize'); -const initProfiler = require('./middlewares/init-profiler'); -const checkJsonContentType = require('./middlewares/check-json-content-type'); -const incrementMapViewCount = require('./middlewares/increment-map-view-count'); -const augmentLayergroupData = require('./middlewares/augment-layergroup-data'); -const cacheControlHeader = require('../../middleware/cache-control-header'); -const cacheChannelHeader = require('../../middleware/cache-channel-header'); -const surrogateKeyHeader = require('../../middleware/surrogate-key-header'); -const lastModifiedHeader = require('../../middleware/last-modified-header'); -const lastUpdatedTimeLayergroup = require('./middlewares/last-updated-time-layergroup'); -const layerStats = require('./middlewares/layer-stats'); -const layergroupIdHeader = require('./middlewares/layergroup-id-header'); -const layergroupMetadata = require('./middlewares/layergroup-metadata'); -const mapError = require('./middlewares/map-error'); +const cleanUpQueryParams = require('../middlewares/clean-up-query-params'); +const credentials = require('../middlewares/credentials'); +const dbConnSetup = require('../middlewares/db-conn-setup'); +const authorize = require('../middlewares/authorize'); +const initProfiler = require('../middlewares/init-profiler'); +const checkJsonContentType = require('../middlewares/check-json-content-type'); +const incrementMapViewCount = require('../middlewares/increment-map-view-count'); +const augmentLayergroupData = require('../middlewares/augment-layergroup-data'); +const cacheControlHeader = require('../middlewares/cache-control-header'); +const cacheChannelHeader = require('../middlewares/cache-channel-header'); +const surrogateKeyHeader = require('../middlewares/surrogate-key-header'); +const lastModifiedHeader = require('../middlewares/last-modified-header'); +const lastUpdatedTimeLayergroup = require('../middlewares/last-updated-time-layergroup'); +const layerStats = require('../middlewares/layer-stats'); +const layergroupIdHeader = require('../middlewares/layergroup-id-header'); +const layergroupMetadata = require('../middlewares/layergroup-metadata'); +const mapError = require('../middlewares/map-error'); const CreateLayergroupMapConfigProvider = require('../../models/mapconfig/provider/create-layergroup-provider'); -const rateLimit = require('../../middleware/rate-limit'); +const rateLimit = require('../middlewares/rate-limit'); const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit; /** - * @param {AuthApi} authApi + * @param {AuthBackend} authBackend * @param {PgConnection} pgConnection * @param {TemplateMaps} templateMaps * @param {MapBackend} mapBackend * @param metadataBackend * @param {SurrogateKeysCache} surrogateKeysCache - * @param {UserLimitsApi} userLimitsApi + * @param {UserLimitsBackend} userLimitsBackend * @param {LayergroupAffectedTables} layergroupAffectedTables * @param {MapConfigAdapter} mapConfigAdapter * @param {StatsBackend} statsBackend @@ -41,11 +41,11 @@ function AnonymousMapController ( mapBackend, metadataBackend, surrogateKeysCache, - userLimitsApi, + userLimitsBackend, layergroupAffectedTables, mapConfigAdapter, statsBackend, - authApi, + authBackend, layergroupMetadata ) { this.pgConnection = pgConnection; @@ -53,11 +53,11 @@ function AnonymousMapController ( this.mapBackend = mapBackend; this.metadataBackend = metadataBackend; this.surrogateKeysCache = surrogateKeysCache; - this.userLimitsApi = userLimitsApi; + this.userLimitsBackend = userLimitsBackend; this.layergroupAffectedTables = layergroupAffectedTables; this.mapConfigAdapter = mapConfigAdapter; this.statsBackend = statsBackend; - this.authApi = authApi; + this.authBackend = authBackend; this.layergroupMetadata = layergroupMetadata; } @@ -78,9 +78,9 @@ AnonymousMapController.prototype.composeCreateMapMiddleware = function () { return [ credentials(), - authorize(this.authApi), + authorize(this.authBackend), dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.ANONYMOUS), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.ANONYMOUS), cleanUpQueryParams(['aggregation']), initProfiler(isTemplateInstantiation), checkJsonContentType(), @@ -88,7 +88,7 @@ AnonymousMapController.prototype.composeCreateMapMiddleware = function () { prepareAdapterMapConfig(this.mapConfigAdapter), createLayergroup ( this.mapBackend, - this.userLimitsApi, + this.userLimitsBackend, this.pgConnection, this.layergroupAffectedTables ), @@ -166,7 +166,7 @@ function prepareAdapterMapConfig (mapConfigAdapter) { }; } -function createLayergroup (mapBackend, userLimitsApi, pgConnection, affectedTablesCache) { +function createLayergroup (mapBackend, userLimitsBackend, pgConnection, affectedTablesCache) { return function createLayergroupMiddleware (req, res, next) { const requestMapConfig = req.body; @@ -185,7 +185,7 @@ function createLayergroup (mapBackend, userLimitsApi, pgConnection, affectedTabl const mapConfigProvider = new CreateLayergroupMapConfigProvider( mapConfig, user, - userLimitsApi, + userLimitsBackend, pgConnection, affectedTablesCache, params @@ -202,6 +202,7 @@ function createLayergroup (mapBackend, userLimitsApi, pgConnection, affectedTabl return next(err); } + res.statusCode = 200; res.body = layergroup; res.locals.mapConfigProvider = mapConfigProvider; diff --git a/lib/cartodb/controllers/layergroup/attributes.js b/lib/cartodb/api/map/attributes-layergroup-controller.js similarity index 64% rename from lib/cartodb/controllers/layergroup/attributes.js rename to lib/cartodb/api/map/attributes-layergroup-controller.js index c4c5af38..632cca9f 100644 --- a/lib/cartodb/controllers/layergroup/attributes.js +++ b/lib/cartodb/api/map/attributes-layergroup-controller.js @@ -1,32 +1,32 @@ -const layergroupToken = require('../../middleware/layergroup-token'); -const cleanUpQueryParams = require('../../middleware/clean-up-query-params'); -const credentials = require('../../middleware/credentials'); -const dbConnSetup = require('../../middleware/db-conn-setup'); -const authorize = require('../../middleware/authorize'); -const rateLimit = require('../../middleware/rate-limit'); +const layergroupToken = require('../middlewares/layergroup-token'); +const cleanUpQueryParams = require('../middlewares/clean-up-query-params'); +const credentials = require('../middlewares/credentials'); +const dbConnSetup = require('../middlewares/db-conn-setup'); +const authorize = require('../middlewares/authorize'); +const rateLimit = require('../middlewares/rate-limit'); const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit; -const createMapStoreMapConfigProvider = require('./middlewares/map-store-map-config-provider'); -const cacheControlHeader = require('../../middleware/cache-control-header'); -const cacheChannelHeader = require('../../middleware/cache-channel-header'); -const surrogateKeyHeader = require('../../middleware/surrogate-key-header'); -const lastModifiedHeader = require('../../middleware/last-modified-header'); +const createMapStoreMapConfigProvider = require('../middlewares/map-store-map-config-provider'); +const cacheControlHeader = require('../middlewares/cache-control-header'); +const cacheChannelHeader = require('../middlewares/cache-channel-header'); +const surrogateKeyHeader = require('../middlewares/surrogate-key-header'); +const lastModifiedHeader = require('../middlewares/last-modified-header'); module.exports = class AttributesLayergroupController { constructor ( attributesBackend, pgConnection, mapStore, - userLimitsApi, + userLimitsBackend, layergroupAffectedTablesCache, - authApi, + authBackend, surrogateKeysCache ) { this.attributesBackend = attributesBackend; this.pgConnection = pgConnection; this.mapStore = mapStore; - this.userLimitsApi = userLimitsApi; + this.userLimitsBackend = userLimitsBackend; this.layergroupAffectedTablesCache = layergroupAffectedTablesCache; - this.authApi = authApi; + this.authBackend = authBackend; this.surrogateKeysCache = surrogateKeysCache; } @@ -35,13 +35,13 @@ module.exports = class AttributesLayergroupController { `/:token/:layer/attributes/:fid`, layergroupToken(), credentials(), - authorize(this.authApi), + authorize(this.authBackend), dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.ATTRIBUTES), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.ATTRIBUTES), cleanUpQueryParams(), createMapStoreMapConfigProvider( this.mapStore, - this.userLimitsApi, + this.userLimitsBackend, this.pgConnection, this.layergroupAffectedTablesCache ), @@ -77,6 +77,7 @@ function getFeatureAttributes (attributesBackend) { return next(err); } + res.statusCode = 200; res.body = tile; next(); diff --git a/lib/cartodb/controllers/layergroup/dataview.js b/lib/cartodb/api/map/dataview-layergroup-controller.js similarity index 75% rename from lib/cartodb/controllers/layergroup/dataview.js rename to lib/cartodb/api/map/dataview-layergroup-controller.js index c13e0eaa..710c5cd4 100644 --- a/lib/cartodb/controllers/layergroup/dataview.js +++ b/lib/cartodb/api/map/dataview-layergroup-controller.js @@ -1,15 +1,15 @@ -const layergroupToken = require('../../middleware/layergroup-token'); -const cleanUpQueryParams = require('../../middleware/clean-up-query-params'); -const credentials = require('../../middleware/credentials'); -const dbConnSetup = require('../../middleware/db-conn-setup'); -const authorize = require('../../middleware/authorize'); -const rateLimit = require('../../middleware/rate-limit'); +const layergroupToken = require('../middlewares/layergroup-token'); +const cleanUpQueryParams = require('../middlewares/clean-up-query-params'); +const credentials = require('../middlewares/credentials'); +const dbConnSetup = require('../middlewares/db-conn-setup'); +const authorize = require('../middlewares/authorize'); +const rateLimit = require('../middlewares/rate-limit'); const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit; -const createMapStoreMapConfigProvider = require('./middlewares/map-store-map-config-provider'); -const cacheControlHeader = require('../../middleware/cache-control-header'); -const cacheChannelHeader = require('../../middleware/cache-channel-header'); -const surrogateKeyHeader = require('../../middleware/surrogate-key-header'); -const lastModifiedHeader = require('../../middleware/last-modified-header'); +const createMapStoreMapConfigProvider = require('../middlewares/map-store-map-config-provider'); +const cacheControlHeader = require('../middlewares/cache-control-header'); +const cacheChannelHeader = require('../middlewares/cache-channel-header'); +const surrogateKeyHeader = require('../middlewares/surrogate-key-header'); +const lastModifiedHeader = require('../middlewares/last-modified-header'); const ALLOWED_DATAVIEW_QUERY_PARAMS = [ 'filters', // json @@ -31,17 +31,17 @@ module.exports = class DataviewLayergroupController { dataviewBackend, pgConnection, mapStore, - userLimitsApi, + userLimitsBackend, layergroupAffectedTablesCache, - authApi, + authBackend, surrogateKeysCache ) { this.dataviewBackend = dataviewBackend; this.pgConnection = pgConnection; this.mapStore = mapStore; - this.userLimitsApi = userLimitsApi; + this.userLimitsBackend = userLimitsBackend; this.layergroupAffectedTablesCache = layergroupAffectedTablesCache; - this.authApi = authApi; + this.authBackend = authBackend; this.surrogateKeysCache = surrogateKeysCache; } @@ -53,13 +53,13 @@ module.exports = class DataviewLayergroupController { `/:token/dataview/:dataviewName`, layergroupToken(), credentials(), - authorize(this.authApi), + authorize(this.authBackend), dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.DATAVIEW), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.DATAVIEW), cleanUpQueryParams(ALLOWED_DATAVIEW_QUERY_PARAMS), createMapStoreMapConfigProvider( this.mapStore, - this.userLimitsApi, + this.userLimitsBackend, this.pgConnection, this.layergroupAffectedTablesCache ), @@ -74,13 +74,13 @@ module.exports = class DataviewLayergroupController { `/:token/:layer/widget/:dataviewName`, layergroupToken(), credentials(), - authorize(this.authApi), + authorize(this.authBackend), dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.DATAVIEW), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.DATAVIEW), cleanUpQueryParams(ALLOWED_DATAVIEW_QUERY_PARAMS), createMapStoreMapConfigProvider( this.mapStore, - this.userLimitsApi, + this.userLimitsBackend, this.pgConnection, this.layergroupAffectedTablesCache ), @@ -95,13 +95,13 @@ module.exports = class DataviewLayergroupController { `/:token/dataview/:dataviewName/search`, layergroupToken(), credentials(), - authorize(this.authApi), + authorize(this.authBackend), dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.DATAVIEW_SEARCH), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.DATAVIEW_SEARCH), cleanUpQueryParams(ALLOWED_DATAVIEW_QUERY_PARAMS), createMapStoreMapConfigProvider( this.mapStore, - this.userLimitsApi, + this.userLimitsBackend, this.pgConnection, this.layergroupAffectedTablesCache ), @@ -116,13 +116,13 @@ module.exports = class DataviewLayergroupController { `/:token/:layer/widget/:dataviewName/search`, layergroupToken(), credentials(), - authorize(this.authApi), + authorize(this.authBackend), dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.DATAVIEW_SEARCH), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.DATAVIEW_SEARCH), cleanUpQueryParams(ALLOWED_DATAVIEW_QUERY_PARAMS), createMapStoreMapConfigProvider( this.mapStore, - this.userLimitsApi, + this.userLimitsBackend, this.pgConnection, this.layergroupAffectedTablesCache ), @@ -151,6 +151,7 @@ function getDataview (dataviewBackend) { return next(err); } + res.statusCode = 200; res.body = dataview; next(); @@ -174,6 +175,7 @@ function dataviewSearch (dataviewBackend) { return next(err); } + res.statusCode = 200; res.body = searchResult; next(); diff --git a/lib/cartodb/controllers/map-router.js b/lib/cartodb/api/map/map-router.js similarity index 68% rename from lib/cartodb/controllers/map-router.js rename to lib/cartodb/api/map/map-router.js index d02cd563..03f19937 100644 --- a/lib/cartodb/controllers/map-router.js +++ b/lib/cartodb/api/map/map-router.js @@ -1,13 +1,13 @@ const { Router: router } = require('express'); -const AnalysisLayergroupController = require('./layergroup/analysis'); -const AttributesLayergroupController = require('./layergroup/attributes'); -const DataviewLayergroupController = require('./layergroup/dataview'); -const PreviewLayergroupController = require('./layergroup/preview'); -const TileLayergroupController = require('./layergroup/tile'); -const AnonymousMapController = require('./map/anonymous'); -const PreviewTemplateController = require('./template/preview'); -const AnalysesController = require('./analyses'); +const AnalysisLayergroupController = require('./analysis-layergroup-controller'); +const AttributesLayergroupController = require('./attributes-layergroup-controller'); +const DataviewLayergroupController = require('./dataview-layergroup-controller'); +const PreviewLayergroupController = require('./preview-layergroup-controller'); +const TileLayergroupController = require('./tile-layergroup-controller'); +const AnonymousMapController = require('./anonymous-map-controller'); +const PreviewTemplateController = require('./preview-template-controller'); +const AnalysesCatalogController = require('./analyses-catalog-controller'); module.exports = class MapRouter { constructor ({ collaborators }) { @@ -19,9 +19,9 @@ module.exports = class MapRouter { tileBackend, pgConnection, mapStore, - userLimitsApi, + userLimitsBackend, layergroupAffectedTablesCache, - authApi, + authBackend, surrogateKeysCache, templateMaps, mapBackend, @@ -30,26 +30,23 @@ module.exports = class MapRouter { statsBackend, layergroupMetadata, namedMapProviderCache, - tablesExtentApi + tablesExtentBackend } = collaborators; this.analysisLayergroupController = new AnalysisLayergroupController( analysisStatusBackend, pgConnection, - mapStore, - userLimitsApi, - layergroupAffectedTablesCache, - authApi, - surrogateKeysCache + userLimitsBackend, + authBackend ); this.attributesLayergroupController = new AttributesLayergroupController( attributesBackend, pgConnection, mapStore, - userLimitsApi, + userLimitsBackend, layergroupAffectedTablesCache, - authApi, + authBackend, surrogateKeysCache ); @@ -57,9 +54,9 @@ module.exports = class MapRouter { dataviewBackend, pgConnection, mapStore, - userLimitsApi, + userLimitsBackend, layergroupAffectedTablesCache, - authApi, + authBackend, surrogateKeysCache ); @@ -67,9 +64,9 @@ module.exports = class MapRouter { previewBackend, pgConnection, mapStore, - userLimitsApi, + userLimitsBackend, layergroupAffectedTablesCache, - authApi, + authBackend, surrogateKeysCache ); @@ -77,9 +74,9 @@ module.exports = class MapRouter { tileBackend, pgConnection, mapStore, - userLimitsApi, + userLimitsBackend, layergroupAffectedTablesCache, - authApi, + authBackend, surrogateKeysCache ); @@ -89,11 +86,11 @@ module.exports = class MapRouter { mapBackend, metadataBackend, surrogateKeysCache, - userLimitsApi, + userLimitsBackend, layergroupAffectedTablesCache, mapConfigAdapter, statsBackend, - authApi, + authBackend, layergroupMetadata ); @@ -101,21 +98,21 @@ module.exports = class MapRouter { namedMapProviderCache, previewBackend, surrogateKeysCache, - tablesExtentApi, + tablesExtentBackend, metadataBackend, pgConnection, - authApi, - userLimitsApi + authBackend, + userLimitsBackend ); - this.analysesController = new AnalysesController( + this.analysesController = new AnalysesCatalogController( pgConnection, - authApi, - userLimitsApi + authBackend, + userLimitsBackend ); } - register (apiRouter) { + register (apiRouter, mapPaths) { const mapRouter = router(); this.analysisLayergroupController.register(mapRouter); @@ -127,11 +124,6 @@ module.exports = class MapRouter { this.previewTemplateController.register(mapRouter); this.analysesController.register(mapRouter); - const paths = [ - '/map', - '/layergroup' - ]; - - apiRouter.use(`(?:${paths.join('|')})`, mapRouter); + mapPaths.forEach(path => apiRouter.use(path, mapRouter)); } }; diff --git a/lib/cartodb/controllers/layergroup/preview.js b/lib/cartodb/api/map/preview-layergroup-controller.js similarity index 75% rename from lib/cartodb/controllers/layergroup/preview.js rename to lib/cartodb/api/map/preview-layergroup-controller.js index 6f1ed363..29db8729 100644 --- a/lib/cartodb/controllers/layergroup/preview.js +++ b/lib/cartodb/api/map/preview-layergroup-controller.js @@ -1,33 +1,33 @@ -const layergroupToken = require('../../middleware/layergroup-token'); -const coordinates = require('../../middleware/coordinates'); -const cleanUpQueryParams = require('../../middleware/clean-up-query-params'); -const credentials = require('../../middleware/credentials'); -const dbConnSetup = require('../../middleware/db-conn-setup'); -const authorize = require('../../middleware/authorize'); -const rateLimit = require('../../middleware/rate-limit'); +const layergroupToken = require('../middlewares/layergroup-token'); +const coordinates = require('../middlewares/coordinates'); +const cleanUpQueryParams = require('../middlewares/clean-up-query-params'); +const credentials = require('../middlewares/credentials'); +const dbConnSetup = require('../middlewares/db-conn-setup'); +const authorize = require('../middlewares/authorize'); +const rateLimit = require('../middlewares/rate-limit'); const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit; -const createMapStoreMapConfigProvider = require('./middlewares/map-store-map-config-provider'); -const cacheControlHeader = require('../../middleware/cache-control-header'); -const cacheChannelHeader = require('../../middleware/cache-channel-header'); -const surrogateKeyHeader = require('../../middleware/surrogate-key-header'); -const lastModifiedHeader = require('../../middleware/last-modified-header'); +const createMapStoreMapConfigProvider = require('../middlewares/map-store-map-config-provider'); +const cacheControlHeader = require('../middlewares/cache-control-header'); +const cacheChannelHeader = require('../middlewares/cache-channel-header'); +const surrogateKeyHeader = require('../middlewares/surrogate-key-header'); +const lastModifiedHeader = require('../middlewares/last-modified-header'); module.exports = class PreviewLayergroupController { constructor ( previewBackend, pgConnection, mapStore, - userLimitsApi, + userLimitsBackend, layergroupAffectedTablesCache, - authApi, + authBackend, surrogateKeysCache ) { this.previewBackend = previewBackend; this.pgConnection = pgConnection; this.mapStore = mapStore; - this.userLimitsApi = userLimitsApi; + this.userLimitsBackend = userLimitsBackend; this.layergroupAffectedTablesCache = layergroupAffectedTablesCache; - this.authApi = authApi; + this.authBackend = authBackend; this.surrogateKeysCache = surrogateKeysCache; } @@ -39,13 +39,13 @@ module.exports = class PreviewLayergroupController { layergroupToken(), coordinates({ z: true, x: false, y: false }), credentials(), - authorize(this.authApi), + authorize(this.authBackend), dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.STATIC), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.STATIC), cleanUpQueryParams(['layer']), createMapStoreMapConfigProvider( this.mapStore, - this.userLimitsApi, + this.userLimitsBackend, this.pgConnection, this.layergroupAffectedTablesCache, forcedFormat @@ -61,13 +61,13 @@ module.exports = class PreviewLayergroupController { `/static/bbox/:token/:west,:south,:east,:north/:width/:height.:format`, layergroupToken(), credentials(), - authorize(this.authApi), + authorize(this.authBackend), dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.STATIC), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.STATIC), cleanUpQueryParams(['layer']), createMapStoreMapConfigProvider( this.mapStore, - this.userLimitsApi, + this.userLimitsBackend, this.pgConnection, this.layergroupAffectedTablesCache, forcedFormat @@ -109,6 +109,7 @@ function getPreviewImageByCenter (previewBackend) { res.set('Content-Type', headers['Content-Type'] || `image/${format}`); + res.statusCode = 200; res.body = image; next(); @@ -144,6 +145,7 @@ function getPreviewImageByBoundingBox (previewBackend) { res.set('Content-Type', headers['Content-Type'] || `image/${format}`); + res.statusCode = 200; res.body = image; next(); diff --git a/lib/cartodb/controllers/template/preview.js b/lib/cartodb/api/map/preview-template-controller.js similarity index 87% rename from lib/cartodb/controllers/template/preview.js rename to lib/cartodb/api/map/preview-template-controller.js index 73eec751..9f5257a3 100644 --- a/lib/cartodb/controllers/template/preview.js +++ b/lib/cartodb/api/map/preview-template-controller.js @@ -1,13 +1,13 @@ -const cleanUpQueryParams = require('../../middleware/clean-up-query-params'); -const credentials = require('../../middleware/credentials'); -const dbConnSetup = require('../../middleware/db-conn-setup'); -const authorize = require('../../middleware/authorize'); -const namedMapProvider = require('./middlewares/named-map-provider'); -const cacheControlHeader = require('../../middleware/cache-control-header'); -const cacheChannelHeader = require('../../middleware/cache-channel-header'); -const surrogateKeyHeader = require('../../middleware/surrogate-key-header'); -const lastModifiedHeader = require('../../middleware/last-modified-header'); -const rateLimit = require('../../middleware/rate-limit'); +const cleanUpQueryParams = require('../middlewares/clean-up-query-params'); +const credentials = require('../middlewares/credentials'); +const dbConnSetup = require('../middlewares/db-conn-setup'); +const authorize = require('../middlewares/authorize'); +const namedMapProvider = require('../middlewares/named-map-provider'); +const cacheControlHeader = require('../middlewares/cache-control-header'); +const cacheChannelHeader = require('../middlewares/cache-channel-header'); +const surrogateKeyHeader = require('../middlewares/surrogate-key-header'); +const lastModifiedHeader = require('../middlewares/last-modified-header'); +const rateLimit = require('../middlewares/rate-limit'); const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit; const DEFAULT_ZOOM_CENTER = { @@ -26,20 +26,20 @@ function PreviewTemplateController ( namedMapProviderCache, previewBackend, surrogateKeysCache, - tablesExtentApi, + tablesExtentBackend, metadataBackend, pgConnection, - authApi, - userLimitsApi + authBackend, + userLimitsBackend ) { this.namedMapProviderCache = namedMapProviderCache; this.previewBackend = previewBackend; this.surrogateKeysCache = surrogateKeysCache; - this.tablesExtentApi = tablesExtentApi; + this.tablesExtentBackend = tablesExtentBackend; this.metadataBackend = metadataBackend; this.pgConnection = pgConnection; - this.authApi = authApi; - this.userLimitsApi = userLimitsApi; + this.authBackend = authBackend; + this.userLimitsBackend = userLimitsBackend; } module.exports = PreviewTemplateController; @@ -48,9 +48,9 @@ PreviewTemplateController.prototype.register = function (mapRouter) { mapRouter.get( `/static/named/:template_id/:width/:height.:format`, credentials(), - authorize(this.authApi), + authorize(this.authBackend), dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.STATIC_NAMED), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.STATIC_NAMED), cleanUpQueryParams(['layer', 'zoom', 'lon', 'lat', 'bbox']), namedMapProvider({ namedMapProviderCache: this.namedMapProviderCache, @@ -61,7 +61,7 @@ PreviewTemplateController.prototype.register = function (mapRouter) { namedMapProviderCache: this.namedMapProviderCache, label: 'STATIC_VIZ_MAP' }), - getStaticImageOptions({ tablesExtentApi: this.tablesExtentApi }), + getStaticImageOptions({ tablesExtentBackend: this.tablesExtentBackend }), getImage({ previewBackend: this.previewBackend, label: 'STATIC_VIZ_MAP' }), setContentTypeHeader(), incrementMapViews({ metadataBackend: this.metadataBackend }), @@ -138,7 +138,7 @@ function prepareLayerFilterFromPreviewLayers ({ namedMapProviderCache, label }) }; } -function getStaticImageOptions ({ tablesExtentApi }) { +function getStaticImageOptions ({ tablesExtentBackend }) { return function getStaticImageOptionsMiddleware(req, res, next) { const { user, mapConfigProvider, template } = res.locals; const { zoom, lon, lat, bbox } = req.query; @@ -164,7 +164,7 @@ function getStaticImageOptions ({ tablesExtentApi }) { return next(); } - tablesExtentApi.getBounds(user, tables, (err, bounds) => { + tablesExtentBackend.getBounds(user, tables, (err, bounds) => { if (err) { return next(); } @@ -268,6 +268,7 @@ function getImage({ previewBackend, label }) { res.set(headers); } + res.statusCode = 200; res.body = image; next(); @@ -287,6 +288,7 @@ function getImage({ previewBackend, label }) { res.set(headers); } + res.statusCode = 200; res.body = image; next(); diff --git a/lib/cartodb/controllers/layergroup/tile.js b/lib/cartodb/api/map/tile-layergroup-controller.js similarity index 51% rename from lib/cartodb/controllers/layergroup/tile.js rename to lib/cartodb/api/map/tile-layergroup-controller.js index 976e3cf9..f882d13c 100644 --- a/lib/cartodb/controllers/layergroup/tile.js +++ b/lib/cartodb/api/map/tile-layergroup-controller.js @@ -1,17 +1,17 @@ -const layergroupToken = require('../../middleware/layergroup-token'); -const coordinates = require('../../middleware/coordinates'); -const cleanUpQueryParams = require('../../middleware/clean-up-query-params'); -const credentials = require('../../middleware/credentials'); -const dbConnSetup = require('../../middleware/db-conn-setup'); -const authorize = require('../../middleware/authorize'); -const rateLimit = require('../../middleware/rate-limit'); +const layergroupToken = require('../middlewares/layergroup-token'); +const coordinates = require('../middlewares/coordinates'); +const cleanUpQueryParams = require('../middlewares/clean-up-query-params'); +const credentials = require('../middlewares/credentials'); +const dbConnSetup = require('../middlewares/db-conn-setup'); +const authorize = require('../middlewares/authorize'); +const rateLimit = require('../middlewares/rate-limit'); const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit; -const createMapStoreMapConfigProvider = require('./middlewares/map-store-map-config-provider'); -const cacheControlHeader = require('../../middleware/cache-control-header'); -const cacheChannelHeader = require('../../middleware/cache-channel-header'); -const surrogateKeyHeader = require('../../middleware/surrogate-key-header'); -const lastModifiedHeader = require('../../middleware/last-modified-header'); -const vectorError = require('../../middleware/vector-error'); +const createMapStoreMapConfigProvider = require('../middlewares/map-store-map-config-provider'); +const cacheControlHeader = require('../middlewares/cache-control-header'); +const cacheChannelHeader = require('../middlewares/cache-channel-header'); +const surrogateKeyHeader = require('../middlewares/surrogate-key-header'); +const lastModifiedHeader = require('../middlewares/last-modified-header'); +const vectorError = require('../middlewares/vector-error'); const SUPPORTED_FORMATS = { grid_json: true, @@ -27,94 +27,43 @@ module.exports = class TileLayergroupController { tileBackend, pgConnection, mapStore, - userLimitsApi, + userLimitsBackend, layergroupAffectedTablesCache, - authApi, + authBackend, surrogateKeysCache ) { this.tileBackend = tileBackend; this.pgConnection = pgConnection; this.mapStore = mapStore; - this.userLimitsApi = userLimitsApi; + this.userLimitsBackend = userLimitsBackend; this.layergroupAffectedTablesCache = layergroupAffectedTablesCache; - this.authApi = authApi; + this.authBackend = authBackend; this.surrogateKeysCache = surrogateKeysCache; } register (mapRouter) { - // REGEXP matches with positive and negative numnbers - const number = () => `(-?\\d+)`; // REGEXP doesn't match with `val` const not = (val) => `(?!${val})([^\/]+?)`; - mapRouter.get( - `/:token/:z${number()}/:x${number()}/:y${number()}@:scale_factor${number()}?x.:format`, + mapRouter.get([ + `/:token/:z/:x/:y@:scale_factor?x.:format`, + `/:token/:z/:x/:y.:format`, + `/:token${not('static')}/:layer/:z/:x/:y.(:format)` + ], layergroupToken(), coordinates(), credentials(), - authorize(this.authApi), + authorize(this.authBackend), dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.TILE), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.TILE), cleanUpQueryParams(), createMapStoreMapConfigProvider( this.mapStore, - this.userLimitsApi, + this.userLimitsBackend, this.pgConnection, this.layergroupAffectedTablesCache ), - getTile(this.tileBackend, 'map_tile'), - cacheControlHeader(), - cacheChannelHeader(), - surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }), - lastModifiedHeader(), - incrementSuccessMetrics(global.statsClient), - incrementErrorMetrics(global.statsClient), - tileError(), - vectorError() - ); - - mapRouter.get( - `/:token/:z${number()}/:x${number()}/:y${number()}.:format`, - layergroupToken(), - coordinates(), - credentials(), - authorize(this.authApi), - dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.TILE), - cleanUpQueryParams(), - createMapStoreMapConfigProvider( - this.mapStore, - this.userLimitsApi, - this.pgConnection, - this.layergroupAffectedTablesCache - ), - getTile(this.tileBackend, 'map_tile'), - cacheControlHeader(), - cacheChannelHeader(), - surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }), - lastModifiedHeader(), - incrementSuccessMetrics(global.statsClient), - incrementErrorMetrics(global.statsClient), - tileError(), - vectorError() - ); - - mapRouter.get( - `/:token${not('static')}/:layer/:z${number()}/:x${number()}/:y${number()}.(:format)`, - layergroupToken(), - coordinates(), - credentials(), - authorize(this.authApi), - dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.TILE), - cleanUpQueryParams(), - createMapStoreMapConfigProvider( - this.mapStore, - this.userLimitsApi, - this.pgConnection, - this.layergroupAffectedTablesCache - ), - getTile(this.tileBackend, 'maplayer_tile'), + getTile(this.tileBackend), cacheControlHeader(), cacheChannelHeader(), surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }), @@ -136,9 +85,9 @@ function getStatusCode(tile, format){ return tile.length === 0 && format === 'mvt' ? 204 : 200; } -function getTile (tileBackend, profileLabel = 'tile') { +function getTile (tileBackend) { return function getTileMiddleware (req, res, next) { - req.profiler.start(`windshaft.${profileLabel}`); + req.profiler.start(`windshaft.${req.params.layer ? 'maplayer_tile' : 'map_tile'}`); const { mapConfigProvider } = res.locals; const { token } = res.locals; diff --git a/lib/cartodb/controllers/map/middlewares/augment-layergroup-data.js b/lib/cartodb/api/middlewares/augment-layergroup-data.js similarity index 100% rename from lib/cartodb/controllers/map/middlewares/augment-layergroup-data.js rename to lib/cartodb/api/middlewares/augment-layergroup-data.js diff --git a/lib/cartodb/middleware/authorize.js b/lib/cartodb/api/middlewares/authorize.js similarity index 78% rename from lib/cartodb/middleware/authorize.js rename to lib/cartodb/api/middlewares/authorize.js index a1323fa9..54cab1c4 100644 --- a/lib/cartodb/middleware/authorize.js +++ b/lib/cartodb/api/middlewares/authorize.js @@ -1,6 +1,6 @@ -module.exports = function authorize (authApi) { +module.exports = function authorize (authBackend) { return function authorizeMiddleware (req, res, next) { - authApi.authorize(req, res, (err, authorized) => { + authBackend.authorize(req, res, (err, authorized) => { req.profiler.done('authorize'); if (err) { diff --git a/lib/cartodb/middleware/cache-channel-header.js b/lib/cartodb/api/middlewares/cache-channel-header.js similarity index 100% rename from lib/cartodb/middleware/cache-channel-header.js rename to lib/cartodb/api/middlewares/cache-channel-header.js diff --git a/lib/cartodb/middleware/cache-control-header.js b/lib/cartodb/api/middlewares/cache-control-header.js similarity index 100% rename from lib/cartodb/middleware/cache-control-header.js rename to lib/cartodb/api/middlewares/cache-control-header.js diff --git a/lib/cartodb/controllers/map/middlewares/check-json-content-type.js b/lib/cartodb/api/middlewares/check-json-content-type.js similarity index 100% rename from lib/cartodb/controllers/map/middlewares/check-json-content-type.js rename to lib/cartodb/api/middlewares/check-json-content-type.js diff --git a/lib/cartodb/middleware/clean-up-query-params.js b/lib/cartodb/api/middlewares/clean-up-query-params.js similarity index 100% rename from lib/cartodb/middleware/clean-up-query-params.js rename to lib/cartodb/api/middlewares/clean-up-query-params.js diff --git a/lib/cartodb/middleware/coordinates.js b/lib/cartodb/api/middlewares/coordinates.js similarity index 100% rename from lib/cartodb/middleware/coordinates.js rename to lib/cartodb/api/middlewares/coordinates.js diff --git a/lib/cartodb/middleware/cors.js b/lib/cartodb/api/middlewares/cors.js similarity index 100% rename from lib/cartodb/middleware/cors.js rename to lib/cartodb/api/middlewares/cors.js diff --git a/lib/cartodb/middleware/credentials.js b/lib/cartodb/api/middlewares/credentials.js similarity index 100% rename from lib/cartodb/middleware/credentials.js rename to lib/cartodb/api/middlewares/credentials.js diff --git a/lib/cartodb/middleware/db-conn-setup.js b/lib/cartodb/api/middlewares/db-conn-setup.js similarity index 100% rename from lib/cartodb/middleware/db-conn-setup.js rename to lib/cartodb/api/middlewares/db-conn-setup.js diff --git a/lib/cartodb/middleware/error-middleware.js b/lib/cartodb/api/middlewares/error-middleware.js similarity index 100% rename from lib/cartodb/middleware/error-middleware.js rename to lib/cartodb/api/middlewares/error-middleware.js diff --git a/lib/cartodb/controllers/map/middlewares/increment-map-view-count.js b/lib/cartodb/api/middlewares/increment-map-view-count.js similarity index 100% rename from lib/cartodb/controllers/map/middlewares/increment-map-view-count.js rename to lib/cartodb/api/middlewares/increment-map-view-count.js diff --git a/lib/cartodb/controllers/map/middlewares/init-profiler.js b/lib/cartodb/api/middlewares/init-profiler.js similarity index 100% rename from lib/cartodb/controllers/map/middlewares/init-profiler.js rename to lib/cartodb/api/middlewares/init-profiler.js diff --git a/lib/cartodb/api/middlewares/initialize-status-code.js b/lib/cartodb/api/middlewares/initialize-status-code.js new file mode 100644 index 00000000..ed6b1805 --- /dev/null +++ b/lib/cartodb/api/middlewares/initialize-status-code.js @@ -0,0 +1,9 @@ +module.exports = function initializeStatusCode () { + return function initializeStatusCodeMiddleware (req, res, next) { + if (req.method !== 'OPTIONS') { + res.statusCode = 404; + } + + next(); + }; +}; diff --git a/lib/cartodb/middleware/last-modified-header.js b/lib/cartodb/api/middlewares/last-modified-header.js similarity index 100% rename from lib/cartodb/middleware/last-modified-header.js rename to lib/cartodb/api/middlewares/last-modified-header.js diff --git a/lib/cartodb/controllers/map/middlewares/last-updated-time-layergroup.js b/lib/cartodb/api/middlewares/last-updated-time-layergroup.js similarity index 100% rename from lib/cartodb/controllers/map/middlewares/last-updated-time-layergroup.js rename to lib/cartodb/api/middlewares/last-updated-time-layergroup.js diff --git a/lib/cartodb/controllers/map/middlewares/layer-stats.js b/lib/cartodb/api/middlewares/layer-stats.js similarity index 100% rename from lib/cartodb/controllers/map/middlewares/layer-stats.js rename to lib/cartodb/api/middlewares/layer-stats.js diff --git a/lib/cartodb/controllers/map/middlewares/layergroup-id-header.js b/lib/cartodb/api/middlewares/layergroup-id-header.js similarity index 100% rename from lib/cartodb/controllers/map/middlewares/layergroup-id-header.js rename to lib/cartodb/api/middlewares/layergroup-id-header.js diff --git a/lib/cartodb/controllers/map/middlewares/layergroup-metadata.js b/lib/cartodb/api/middlewares/layergroup-metadata.js similarity index 100% rename from lib/cartodb/controllers/map/middlewares/layergroup-metadata.js rename to lib/cartodb/api/middlewares/layergroup-metadata.js diff --git a/lib/cartodb/middleware/layergroup-token.js b/lib/cartodb/api/middlewares/layergroup-token.js similarity index 93% rename from lib/cartodb/middleware/layergroup-token.js rename to lib/cartodb/api/middlewares/layergroup-token.js index 1a32e413..0e6553d2 100644 --- a/lib/cartodb/middleware/layergroup-token.js +++ b/lib/cartodb/api/middlewares/layergroup-token.js @@ -1,4 +1,4 @@ -const LayergroupToken = require('../models/layergroup-token'); +const LayergroupToken = require('../../models/layergroup-token'); const authErrorMessageTemplate = function (signer, user) { return `Cannot use map signature of user "${signer}" on db of user "${user}"`; }; diff --git a/lib/cartodb/middleware/logger.js b/lib/cartodb/api/middlewares/logger.js similarity index 100% rename from lib/cartodb/middleware/logger.js rename to lib/cartodb/api/middlewares/logger.js diff --git a/lib/cartodb/middleware/lzma.js b/lib/cartodb/api/middlewares/lzma.js similarity index 100% rename from lib/cartodb/middleware/lzma.js rename to lib/cartodb/api/middlewares/lzma.js diff --git a/lib/cartodb/controllers/map/middlewares/map-error.js b/lib/cartodb/api/middlewares/map-error.js similarity index 100% rename from lib/cartodb/controllers/map/middlewares/map-error.js rename to lib/cartodb/api/middlewares/map-error.js diff --git a/lib/cartodb/controllers/layergroup/middlewares/map-store-map-config-provider.js b/lib/cartodb/api/middlewares/map-store-map-config-provider.js similarity index 86% rename from lib/cartodb/controllers/layergroup/middlewares/map-store-map-config-provider.js rename to lib/cartodb/api/middlewares/map-store-map-config-provider.js index 7d64cb01..58cdb79e 100644 --- a/lib/cartodb/controllers/layergroup/middlewares/map-store-map-config-provider.js +++ b/lib/cartodb/api/middlewares/map-store-map-config-provider.js @@ -1,8 +1,8 @@ -const MapStoreMapConfigProvider = require('../../../models/mapconfig/provider/map-store-provider'); +const MapStoreMapConfigProvider = require('../../models/mapconfig/provider/map-store-provider'); module.exports = function createMapStoreMapConfigProvider ( mapStore, - userLimitsApi, + userLimitsBackend, pgConnection, affectedTablesCache, forcedFormat = null @@ -26,7 +26,7 @@ module.exports = function createMapStoreMapConfigProvider ( res.locals.mapConfigProvider = new MapStoreMapConfigProvider( mapStore, user, - userLimitsApi, + userLimitsBackend, pgConnection, affectedTablesCache, params diff --git a/lib/cartodb/controllers/template/middlewares/named-map-provider.js b/lib/cartodb/api/middlewares/named-map-provider.js similarity index 100% rename from lib/cartodb/controllers/template/middlewares/named-map-provider.js rename to lib/cartodb/api/middlewares/named-map-provider.js diff --git a/lib/cartodb/middleware/rate-limit.js b/lib/cartodb/api/middlewares/rate-limit.js similarity index 92% rename from lib/cartodb/middleware/rate-limit.js rename to lib/cartodb/api/middlewares/rate-limit.js index b3c6d7fe..55062d76 100644 --- a/lib/cartodb/middleware/rate-limit.js +++ b/lib/cartodb/api/middlewares/rate-limit.js @@ -19,13 +19,13 @@ const RATE_LIMIT_ENDPOINTS_GROUPS = { NAMED_TILES: 'named_tiles' }; -function rateLimit(userLimitsApi, endpointGroup = null) { +function rateLimit(userLimitsBackend, endpointGroup = null) { if (!isRateLimitEnabled(endpointGroup)) { return function rateLimitDisabledMiddleware(req, res, next) { next(); }; } return function rateLimitMiddleware(req, res, next) { - userLimitsApi.getRateLimit(res.locals.user, endpointGroup, function (err, userRateLimit) { + userLimitsBackend.getRateLimit(res.locals.user, endpointGroup, function (err, userRateLimit) { if (err) { return next(err); } diff --git a/lib/cartodb/middleware/send-response.js b/lib/cartodb/api/middlewares/send-response.js similarity index 89% rename from lib/cartodb/middleware/send-response.js rename to lib/cartodb/api/middlewares/send-response.js index 469cf0a7..ec13c5bf 100644 --- a/lib/cartodb/middleware/send-response.js +++ b/lib/cartodb/api/middlewares/send-response.js @@ -2,7 +2,7 @@ module.exports = function sendResponse () { return function sendResponseMiddleware (req, res) { req.profiler.done('res'); - res.status(res.statusCode || 200); + res.status(res.statusCode); if (Buffer.isBuffer(res.body)) { return res.send(res.body); diff --git a/lib/cartodb/middleware/served-by-host-header.js b/lib/cartodb/api/middlewares/served-by-host-header.js similarity index 100% rename from lib/cartodb/middleware/served-by-host-header.js rename to lib/cartodb/api/middlewares/served-by-host-header.js diff --git a/lib/cartodb/middleware/stats.js b/lib/cartodb/api/middlewares/stats.js similarity index 93% rename from lib/cartodb/middleware/stats.js rename to lib/cartodb/api/middlewares/stats.js index 83ff3054..53d2cf9a 100644 --- a/lib/cartodb/middleware/stats.js +++ b/lib/cartodb/api/middlewares/stats.js @@ -1,4 +1,4 @@ -const Profiler = require('../stats/profiler_proxy'); +const Profiler = require('../../stats/profiler_proxy'); const debug = require('debug')('windshaft:cartodb:stats'); const onHeaders = require('on-headers'); diff --git a/lib/cartodb/middleware/surrogate-key-header.js b/lib/cartodb/api/middlewares/surrogate-key-header.js similarity index 84% rename from lib/cartodb/middleware/surrogate-key-header.js rename to lib/cartodb/api/middlewares/surrogate-key-header.js index 51cec1c1..d2a3243c 100644 --- a/lib/cartodb/middleware/surrogate-key-header.js +++ b/lib/cartodb/api/middlewares/surrogate-key-header.js @@ -1,5 +1,5 @@ -const NamedMapsCacheEntry = require('../cache/model/named_maps_entry'); -const NamedMapMapConfigProvider = require('../models/mapconfig/provider/named-map-provider'); +const NamedMapsCacheEntry = require('../../cache/model/named_maps_entry'); +const NamedMapMapConfigProvider = require('../../models/mapconfig/provider/named-map-provider'); module.exports = function setSurrogateKeyHeader ({ surrogateKeysCache }) { return function setSurrogateKeyHeaderMiddleware(req, res, next) { diff --git a/lib/cartodb/middleware/syntax-error.js b/lib/cartodb/api/middlewares/syntax-error.js similarity index 100% rename from lib/cartodb/middleware/syntax-error.js rename to lib/cartodb/api/middlewares/syntax-error.js diff --git a/lib/cartodb/middleware/user.js b/lib/cartodb/api/middlewares/user.js similarity index 79% rename from lib/cartodb/middleware/user.js rename to lib/cartodb/api/middlewares/user.js index 9c7968bc..551fa001 100644 --- a/lib/cartodb/middleware/user.js +++ b/lib/cartodb/api/middlewares/user.js @@ -1,4 +1,4 @@ -const CdbRequest = require('../models/cdb_request'); +const CdbRequest = require('../../models/cdb_request'); module.exports = function user () { const cdbRequest = new CdbRequest(); diff --git a/lib/cartodb/middleware/vector-error.js b/lib/cartodb/api/middlewares/vector-error.js similarity index 95% rename from lib/cartodb/middleware/vector-error.js rename to lib/cartodb/api/middlewares/vector-error.js index 8268ec1f..7e2ec75f 100644 --- a/lib/cartodb/middleware/vector-error.js +++ b/lib/cartodb/api/middlewares/vector-error.js @@ -1,5 +1,5 @@ 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) { diff --git a/lib/cartodb/controllers/template/admin.js b/lib/cartodb/api/template/admin-template-controller.js similarity index 76% rename from lib/cartodb/controllers/template/admin.js rename to lib/cartodb/api/template/admin-template-controller.js index 3c94b735..b45ebca7 100644 --- a/lib/cartodb/controllers/template/admin.js +++ b/lib/cartodb/api/template/admin-template-controller.js @@ -1,18 +1,18 @@ const { templateName } = require('../../backends/template_maps'); -const credentials = require('../../middleware/credentials'); -const rateLimit = require('../../middleware/rate-limit'); +const credentials = require('../middlewares/credentials'); +const rateLimit = require('../middlewares/rate-limit'); const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit; /** - * @param {AuthApi} authApi + * @param {AuthBackend} authBackend * @param {PgConnection} pgConnection * @param {TemplateMaps} templateMaps * @constructor */ -function AdminTemplateController(authApi, templateMaps, userLimitsApi) { - this.authApi = authApi; +function AdminTemplateController(authBackend, templateMaps, userLimitsBackend) { + this.authBackend = authBackend; this.templateMaps = templateMaps; - this.userLimitsApi = userLimitsApi; + this.userLimitsBackend = userLimitsBackend; } module.exports = AdminTemplateController; @@ -23,8 +23,8 @@ AdminTemplateController.prototype.register = function (templateRouter) { templateRouter.post( `/`, credentials(), - authorizedByAPIKey({ authApi: this.authApi, action: 'create', label: 'POST TEMPLATE' }), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_CREATE), + authorizedByAPIKey({ authBackend: this.authBackend, action: 'create', label: 'POST TEMPLATE' }), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_CREATE), checkContentType({ action: 'POST', label: 'POST TEMPLATE' }), createTemplate({ templateMaps: this.templateMaps }) ); @@ -32,8 +32,8 @@ AdminTemplateController.prototype.register = function (templateRouter) { templateRouter.put( `/:template_id`, credentials(), - authorizedByAPIKey({ authApi: this.authApi, action: 'update', label: 'PUT TEMPLATE' }), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_UPDATE), + authorizedByAPIKey({ authBackend: this.authBackend, action: 'update', label: 'PUT TEMPLATE' }), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_UPDATE), checkContentType({ action: 'PUT', label: 'PUT TEMPLATE' }), updateTemplate({ templateMaps: this.templateMaps }) ); @@ -41,24 +41,24 @@ AdminTemplateController.prototype.register = function (templateRouter) { templateRouter.get( `/:template_id`, credentials(), - authorizedByAPIKey({ authApi: this.authApi, action: 'get', label: 'GET TEMPLATE' }), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_GET), + authorizedByAPIKey({ authBackend: this.authBackend, action: 'get', label: 'GET TEMPLATE' }), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_GET), retrieveTemplate({ templateMaps: this.templateMaps }) ); templateRouter.delete( `/:template_id`, credentials(), - authorizedByAPIKey({ authApi: this.authApi, action: 'delete', label: 'DELETE TEMPLATE' }), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_DELETE), + authorizedByAPIKey({ authBackend: this.authBackend, action: 'delete', label: 'DELETE TEMPLATE' }), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_DELETE), destroyTemplate({ templateMaps: this.templateMaps }) ); templateRouter.get( `/`, credentials(), - authorizedByAPIKey({ authApi: this.authApi, action: 'list', label: 'GET TEMPLATE LIST' }), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_LIST), + authorizedByAPIKey({ authBackend: this.authBackend, action: 'list', label: 'GET TEMPLATE LIST' }), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_LIST), listTemplates({ templateMaps: this.templateMaps }) ); }; @@ -75,11 +75,11 @@ function checkContentType ({ action, label }) { }; } -function authorizedByAPIKey ({ authApi, action, label }) { +function authorizedByAPIKey ({ authBackend, action, label }) { return function authorizedByAPIKeyMiddleware (req, res, next) { const { user } = res.locals; - authApi.authorizedByAPIKey(user, res, (err, authenticated, apikey) => { + authBackend.authorizedByAPIKey(user, res, (err, authenticated, apikey) => { if (err) { return next(err); } @@ -115,6 +115,7 @@ function createTemplate ({ templateMaps }) { return next(err); } + res.statusCode = 200; res.body = { template_id: templateId }; next(); @@ -133,6 +134,7 @@ function updateTemplate ({ templateMaps }) { return next(err); } + res.statusCode = 200; res.body = { template_id: templateId }; next(); @@ -161,6 +163,7 @@ function retrieveTemplate ({ templateMaps }) { // so we remove it before returning to the user delete template.auth_id; + res.statusCode = 200; res.body = { template }; next(); @@ -199,6 +202,7 @@ function listTemplates ({ templateMaps }) { return next(err); } + res.statusCode = 200; res.body = { template_ids: templateIds }; next(); diff --git a/lib/cartodb/controllers/map/named.js b/lib/cartodb/api/template/named-template-controller.js similarity index 75% rename from lib/cartodb/controllers/map/named.js rename to lib/cartodb/api/template/named-template-controller.js index 2258b62f..86613c5e 100644 --- a/lib/cartodb/controllers/map/named.js +++ b/lib/cartodb/api/template/named-template-controller.js @@ -1,33 +1,33 @@ -const cleanUpQueryParams = require('../../middleware/clean-up-query-params'); -const credentials = require('../../middleware/credentials'); -const dbConnSetup = require('../../middleware/db-conn-setup'); -const authorize = require('../../middleware/authorize'); -const initProfiler = require('./middlewares/init-profiler'); -const checkJsonContentType = require('./middlewares/check-json-content-type'); -const incrementMapViewCount = require('./middlewares/increment-map-view-count'); -const augmentLayergroupData = require('./middlewares/augment-layergroup-data'); -const cacheControlHeader = require('../../middleware/cache-control-header'); -const cacheChannelHeader = require('../../middleware/cache-channel-header'); -const surrogateKeyHeader = require('../../middleware/surrogate-key-header'); -const lastModifiedHeader = require('../../middleware/last-modified-header'); -const lastUpdatedTimeLayergroup = require('./middlewares/last-updated-time-layergroup'); -const layerStats = require('./middlewares/layer-stats'); -const layergroupIdHeader = require('./middlewares/layergroup-id-header'); -const layergroupMetadata = require('./middlewares/layergroup-metadata'); -const mapError = require('./middlewares/map-error'); +const cleanUpQueryParams = require('../middlewares/clean-up-query-params'); +const credentials = require('../middlewares/credentials'); +const dbConnSetup = require('../middlewares/db-conn-setup'); +const authorize = require('../middlewares/authorize'); +const initProfiler = require('../middlewares/init-profiler'); +const checkJsonContentType = require('../middlewares/check-json-content-type'); +const incrementMapViewCount = require('../middlewares/increment-map-view-count'); +const augmentLayergroupData = require('../middlewares/augment-layergroup-data'); +const cacheControlHeader = require('../middlewares/cache-control-header'); +const cacheChannelHeader = require('../middlewares/cache-channel-header'); +const surrogateKeyHeader = require('../middlewares/surrogate-key-header'); +const lastModifiedHeader = require('../middlewares/last-modified-header'); +const lastUpdatedTimeLayergroup = require('../middlewares/last-updated-time-layergroup'); +const layerStats = require('../middlewares/layer-stats'); +const layergroupIdHeader = require('../middlewares/layergroup-id-header'); +const layergroupMetadata = require('../middlewares/layergroup-metadata'); +const mapError = require('../middlewares/map-error'); const NamedMapMapConfigProvider = require('../../models/mapconfig/provider/named-map-provider'); const CreateLayergroupMapConfigProvider = require('../../models/mapconfig/provider/create-layergroup-provider'); -const rateLimit = require('../../middleware/rate-limit'); +const rateLimit = require('../middlewares/rate-limit'); const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit; /** - * @param {AuthApi} authApi + * @param {AuthBackend} authBackend * @param {PgConnection} pgConnection * @param {TemplateMaps} templateMaps * @param {MapBackend} mapBackend * @param metadataBackend * @param {SurrogateKeysCache} surrogateKeysCache - * @param {UserLimitsApi} userLimitsApi + * @param {UserLimitsBackend} userLimitsBackend * @param {LayergroupAffectedTables} layergroupAffectedTables * @param {MapConfigAdapter} mapConfigAdapter * @param {StatsBackend} statsBackend @@ -39,11 +39,11 @@ function NamedMapController ( mapBackend, metadataBackend, surrogateKeysCache, - userLimitsApi, + userLimitsBackend, layergroupAffectedTables, mapConfigAdapter, statsBackend, - authApi, + authBackend, layergroupMetadata ) { this.pgConnection = pgConnection; @@ -51,11 +51,11 @@ function NamedMapController ( this.mapBackend = mapBackend; this.metadataBackend = metadataBackend; this.surrogateKeysCache = surrogateKeysCache; - this.userLimitsApi = userLimitsApi; + this.userLimitsBackend = userLimitsBackend; this.layergroupAffectedTables = layergroupAffectedTables; this.mapConfigAdapter = mapConfigAdapter; this.statsBackend = statsBackend; - this.authApi = authApi; + this.authBackend = authBackend; this.layergroupMetadata = layergroupMetadata; } @@ -82,9 +82,9 @@ NamedMapController.prototype.composeInstantiateTemplateMiddleware = function () return [ credentials(), - authorize(this.authApi), + authorize(this.authBackend), dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED), cleanUpQueryParams(['aggregation']), initProfiler(isTemplateInstantiation), checkJsonContentType(), @@ -93,13 +93,13 @@ NamedMapController.prototype.composeInstantiateTemplateMiddleware = function () this.templateMaps, this.pgConnection, this.metadataBackend, - this.userLimitsApi, + this.userLimitsBackend, this.mapConfigAdapter, this.layergroupAffectedTables ), instantiateLayergroup( this.mapBackend, - this.userLimitsApi, + this.userLimitsBackend, this.pgConnection, this.layergroupAffectedTables ), @@ -145,7 +145,7 @@ function getTemplate ( templateMaps, pgConnection, metadataBackend, - userLimitsApi, + userLimitsBackend, mapConfigAdapter, affectedTablesCache ) { @@ -161,7 +161,7 @@ function getTemplate ( templateMaps, pgConnection, metadataBackend, - userLimitsApi, + userLimitsBackend, mapConfigAdapter, affectedTablesCache, user, @@ -186,13 +186,13 @@ function getTemplate ( }; } -function instantiateLayergroup (mapBackend, userLimitsApi, pgConnection, affectedTablesCache) { +function instantiateLayergroup (mapBackend, userLimitsBackend, pgConnection, affectedTablesCache) { return function instantiateLayergroupMiddleware (req, res, next) { const { user, mapConfig, rendererParams } = res.locals; const mapConfigProvider = new CreateLayergroupMapConfigProvider( mapConfig, user, - userLimitsApi, + userLimitsBackend, pgConnection, affectedTablesCache, rendererParams @@ -204,6 +204,7 @@ function instantiateLayergroup (mapBackend, userLimitsApi, pgConnection, affecte return next(err); } + res.statusCode = 200; res.body = layergroup; const { mapConfigProvider } = res.locals; diff --git a/lib/cartodb/controllers/template-router.js b/lib/cartodb/api/template/template-router.js similarity index 71% rename from lib/cartodb/controllers/template-router.js rename to lib/cartodb/api/template/template-router.js index d549dafd..9ddcf9fc 100644 --- a/lib/cartodb/controllers/template-router.js +++ b/lib/cartodb/api/template/template-router.js @@ -1,8 +1,8 @@ const { Router: router } = require('express'); -const NamedMapController = require('./map/named'); -const AdminTemplateController = require('./template/admin'); -const TileTemplateController = require('./template/tile'); +const NamedMapController = require('./named-template-controller'); +const AdminTemplateController = require('./admin-template-controller'); +const TileTemplateController = require('./tile-template-controller'); module.exports = class TemplateRouter { constructor ({ collaborators }) { @@ -12,11 +12,11 @@ module.exports = class TemplateRouter { mapBackend, metadataBackend, surrogateKeysCache, - userLimitsApi, + userLimitsBackend, layergroupAffectedTablesCache, mapConfigAdapter, statsBackend, - authApi, + authBackend, layergroupMetadata, namedMapProviderCache, tileBackend, @@ -28,11 +28,11 @@ module.exports = class TemplateRouter { mapBackend, metadataBackend, surrogateKeysCache, - userLimitsApi, + userLimitsBackend, layergroupAffectedTablesCache, mapConfigAdapter, statsBackend, - authApi, + authBackend, layergroupMetadata ); @@ -41,29 +41,24 @@ module.exports = class TemplateRouter { tileBackend, surrogateKeysCache, pgConnection, - authApi, - userLimitsApi + authBackend, + userLimitsBackend ); this.adminTemplateController = new AdminTemplateController( - authApi, + authBackend, templateMaps, - userLimitsApi + userLimitsBackend ); } - register (apiRouter) { + register (apiRouter, templatePaths) { const templateRouter = router(); this.namedMapController.register(templateRouter); this.tileTemplateController.register(templateRouter); this.adminTemplateController.register(templateRouter); - const paths = [ - '/map/named', - '/template' - ]; - - apiRouter.use(`(?:${paths.join('|')})`, templateRouter); + templatePaths.forEach(path => apiRouter.use(path, templateRouter)); } }; diff --git a/lib/cartodb/controllers/template/tile.js b/lib/cartodb/api/template/tile-template-controller.js similarity index 65% rename from lib/cartodb/controllers/template/tile.js rename to lib/cartodb/api/template/tile-template-controller.js index bb9645c0..de256ccb 100644 --- a/lib/cartodb/controllers/template/tile.js +++ b/lib/cartodb/api/template/tile-template-controller.js @@ -1,15 +1,15 @@ -const coordinates = require('../../middleware/coordinates'); -const cleanUpQueryParams = require('../../middleware/clean-up-query-params'); -const credentials = require('../../middleware/credentials'); -const dbConnSetup = require('../../middleware/db-conn-setup'); -const authorize = require('../../middleware/authorize'); -const namedMapProvider = require('./middlewares/named-map-provider'); -const cacheControlHeader = require('../../middleware/cache-control-header'); -const cacheChannelHeader = require('../../middleware/cache-channel-header'); -const surrogateKeyHeader = require('../../middleware/surrogate-key-header'); -const lastModifiedHeader = require('../../middleware/last-modified-header'); -const vectorError = require('../../middleware/vector-error'); -const rateLimit = require('../../middleware/rate-limit'); +const coordinates = require('../middlewares/coordinates'); +const cleanUpQueryParams = require('../middlewares/clean-up-query-params'); +const credentials = require('../middlewares/credentials'); +const dbConnSetup = require('../middlewares/db-conn-setup'); +const authorize = require('../middlewares/authorize'); +const namedMapProvider = require('../middlewares/named-map-provider'); +const cacheControlHeader = require('../middlewares/cache-control-header'); +const cacheChannelHeader = require('../middlewares/cache-channel-header'); +const surrogateKeyHeader = require('../middlewares/surrogate-key-header'); +const lastModifiedHeader = require('../middlewares/last-modified-header'); +const vectorError = require('../middlewares/vector-error'); +const rateLimit = require('../middlewares/rate-limit'); const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit; function TileTemplateController ( @@ -17,15 +17,15 @@ function TileTemplateController ( tileBackend, surrogateKeysCache, pgConnection, - authApi, - userLimitsApi + authBackend, + userLimitsBackend ) { this.namedMapProviderCache = namedMapProviderCache; this.tileBackend = tileBackend; this.surrogateKeysCache = surrogateKeysCache; this.pgConnection = pgConnection; - this.authApi = authApi; - this.userLimitsApi = userLimitsApi; + this.authBackend = authBackend; + this.userLimitsBackend = userLimitsBackend; } module.exports = TileTemplateController; @@ -35,9 +35,9 @@ TileTemplateController.prototype.register = function (templateRouter) { `/:template_id/:layer/:z/:x/:y.(:format)`, coordinates(), credentials(), - authorize(this.authApi), + authorize(this.authBackend), dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_TILES), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_TILES), cleanUpQueryParams(), namedMapProvider({ namedMapProviderCache: this.namedMapProviderCache, @@ -75,6 +75,7 @@ function getTile ({ tileBackend, label }) { res.set(headers); } + res.statusCode = 200; res.body = tile; next(); diff --git a/lib/cartodb/api/auth_api.js b/lib/cartodb/backends/auth.js similarity index 94% rename from lib/cartodb/api/auth_api.js rename to lib/cartodb/backends/auth.js index ff42c9df..1c0e4e43 100644 --- a/lib/cartodb/api/auth_api.js +++ b/lib/cartodb/backends/auth.js @@ -7,16 +7,16 @@ var _ = require('underscore'); // AUTH_FALLBACK * @param {MapStore} mapStore * @param {TemplateMaps} templateMaps * @constructor - * @type {AuthApi} + * @type {AuthBackend} */ -function AuthApi(pgConnection, metadataBackend, mapStore, templateMaps) { +function AuthBackend(pgConnection, metadataBackend, mapStore, templateMaps) { this.pgConnection = pgConnection; this.metadataBackend = metadataBackend; this.mapStore = mapStore; this.templateMaps = templateMaps; } -module.exports = AuthApi; +module.exports = AuthBackend; // Check if the user is authorized by a signer // @@ -25,7 +25,7 @@ module.exports = AuthApi; // null if the request is not signed by anyone // or will be a string cartodb username otherwise. // -AuthApi.prototype.authorizedBySigner = function(req, res, callback) { +AuthBackend.prototype.authorizedBySigner = function(req, res, callback) { if ( ! res.locals.token || ! res.locals.signer ) { return callback(null, false); // no signer requested } @@ -60,7 +60,7 @@ function isValidApiKey(apikey) { // @param callback function(err, authorized) // NOTE: authorized is expected to be 0 or 1 (integer) // -AuthApi.prototype.authorizedByAPIKey = function(user, res, callback) { +AuthBackend.prototype.authorizedByAPIKey = function(user, res, callback) { const apikeyToken = res.locals.api_key; const basicAuthUsername = res.locals.basicAuthUsername; @@ -160,7 +160,7 @@ function usernameMatches (basicAuthUsername, requestUsername) { * @param res - standard res object. Contains the auth parameters in locals * @param callback function(err, allowed) is access allowed not? */ -AuthApi.prototype.authorize = function(req, res, callback) { +AuthBackend.prototype.authorize = function(req, res, callback) { var user = res.locals.user; this.authorizedByAPIKey(user, res, (err, isAuthorizedByApikey) => { diff --git a/lib/cartodb/api/filter_stats_api.js b/lib/cartodb/backends/filter-stats.js similarity index 89% rename from lib/cartodb/api/filter_stats_api.js rename to lib/cartodb/backends/filter-stats.js index 31e90a25..ba427405 100644 --- a/lib/cartodb/api/filter_stats_api.js +++ b/lib/cartodb/backends/filter-stats.js @@ -2,11 +2,11 @@ var _ = require('underscore'); var step = require('step'); var AnalysisFilter = require('../models/filter/analysis'); -function FilterStatsApi(pgQueryRunner) { +function FilterStatsBackends(pgQueryRunner) { this.pgQueryRunner = pgQueryRunner; } -module.exports = FilterStatsApi; +module.exports = FilterStatsBackends; function getEstimatedRows(pgQueryRunner, username, query, callback) { pgQueryRunner.run(username, "EXPLAIN (FORMAT JSON)"+query, function(err, result_rows) { @@ -23,7 +23,7 @@ function getEstimatedRows(pgQueryRunner, username, query, callback) { }); } -FilterStatsApi.prototype.getFilterStats = function (username, unfiltered_query, filters, callback) { +FilterStatsBackends.prototype.getFilterStats = function (username, unfiltered_query, filters, callback) { var stats = {}; var self = this; step( diff --git a/lib/cartodb/api/overviews_metadata_api.js b/lib/cartodb/backends/overviews-metadata.js similarity index 86% rename from lib/cartodb/api/overviews_metadata_api.js rename to lib/cartodb/backends/overviews-metadata.js index 55b4966f..31045534 100644 --- a/lib/cartodb/api/overviews_metadata_api.js +++ b/lib/cartodb/backends/overviews-metadata.js @@ -1,10 +1,10 @@ var SubstitutionTokens = require('../utils/substitution-tokens'); -function OverviewsMetadataApi(pgQueryRunner) { +function OverviewsMetadataBackend(pgQueryRunner) { this.pgQueryRunner = pgQueryRunner; } -module.exports = OverviewsMetadataApi; +module.exports = OverviewsMetadataBackend; function prepareSql(sql) { return sql && SubstitutionTokens.replace(sql, { @@ -15,7 +15,7 @@ function prepareSql(sql) { }); } -OverviewsMetadataApi.prototype.getOverviewsMetadata = function (username, sql, callback) { +OverviewsMetadataBackend.prototype.getOverviewsMetadata = function (username, sql, callback) { // FIXME: Currently using internal function _cdb_schema_name // CDB_Overviews should provide the schema information directly. var query = 'SELECT *, _cdb_schema_name(base_table)' + diff --git a/lib/cartodb/api/tables_extent_api.js b/lib/cartodb/backends/tables-extent.js similarity index 90% rename from lib/cartodb/api/tables_extent_api.js rename to lib/cartodb/backends/tables-extent.js index 7b534a3f..5e78a6b1 100644 --- a/lib/cartodb/api/tables_extent_api.js +++ b/lib/cartodb/backends/tables-extent.js @@ -1,8 +1,8 @@ -function TablesExtentApi(pgQueryRunner) { +function TablesExtentBackend(pgQueryRunner) { this.pgQueryRunner = pgQueryRunner; } -module.exports = TablesExtentApi; +module.exports = TablesExtentBackend; /** * Given a username and a list of tables it will return the estimated extent in SRID 4326 for all the tables based on @@ -13,7 +13,7 @@ module.exports = TablesExtentApi; * `table_name` format as valid input * @param {Function} callback function(err, result) {Object} result with `west`, `south`, `east`, `north` */ -TablesExtentApi.prototype.getBounds = function (username, tables, callback) { +TablesExtentBackend.prototype.getBounds = function (username, tables, callback) { var estimatedExtentSQLs = tables.map(function(table) { return "ST_EstimatedExtent('" + table.schema_name + "', '" + table.table_name + "', 'the_geom_webmercator')"; }); diff --git a/lib/cartodb/api/user_limits_api.js b/lib/cartodb/backends/user-limits.js similarity index 81% rename from lib/cartodb/api/user_limits_api.js rename to lib/cartodb/backends/user-limits.js index caf9f151..519f1cd1 100644 --- a/lib/cartodb/api/user_limits_api.js +++ b/lib/cartodb/backends/user-limits.js @@ -5,9 +5,9 @@ var step = require('step'); * @param metadataBackend * @param options * @constructor - * @type {UserLimitsApi} + * @type {UserLimitsBackend} */ -function UserLimitsApi(metadataBackend, options) { +function UserLimitsBackend(metadataBackend, options) { this.metadataBackend = metadataBackend; this.options = options || {}; this.options.limits = this.options.limits || {}; @@ -15,9 +15,9 @@ function UserLimitsApi(metadataBackend, options) { this.preprareRateLimit(); } -module.exports = UserLimitsApi; +module.exports = UserLimitsBackend; -UserLimitsApi.prototype.getRenderLimits = function (username, apiKey, callback) { +UserLimitsBackend.prototype.getRenderLimits = function (username, apiKey, callback) { var self = this; var limits = { @@ -40,7 +40,7 @@ UserLimitsApi.prototype.getRenderLimits = function (username, apiKey, callback) }); }; -UserLimitsApi.prototype.getTimeoutRenderLimit = function (username, apiKey, callback) { +UserLimitsBackend.prototype.getTimeoutRenderLimit = function (username, apiKey, callback) { var self = this; step( @@ -80,12 +80,12 @@ UserLimitsApi.prototype.getTimeoutRenderLimit = function (username, apiKey, call ); }; -UserLimitsApi.prototype.preprareRateLimit = function () { +UserLimitsBackend.prototype.preprareRateLimit = function () { if (this.options.limits.rateLimitsEnabled) { this.metadataBackend.loadRateLimitsScript(); } }; -UserLimitsApi.prototype.getRateLimit = function (user, endpointGroup, callback) { +UserLimitsBackend.prototype.getRateLimit = function (user, endpointGroup, callback) { this.metadataBackend.getRateLimit(user, 'maps', endpointGroup, callback); }; diff --git a/lib/cartodb/cache/named_map_provider_cache.js b/lib/cartodb/cache/named_map_provider_cache.js index e0850822..b64decb1 100644 --- a/lib/cartodb/cache/named_map_provider_cache.js +++ b/lib/cartodb/cache/named_map_provider_cache.js @@ -10,14 +10,14 @@ function NamedMapProviderCache( templateMaps, pgConnection, metadataBackend, - userLimitsApi, + userLimitsBackend, mapConfigAdapter, affectedTablesCache ) { this.templateMaps = templateMaps; this.pgConnection = pgConnection; this.metadataBackend = metadataBackend; - this.userLimitsApi = userLimitsApi; + this.userLimitsBackend = userLimitsBackend; this.mapConfigAdapter = mapConfigAdapter; this.affectedTablesCache = affectedTablesCache; @@ -36,7 +36,7 @@ NamedMapProviderCache.prototype.get = function(user, templateId, config, authTok this.templateMaps, this.pgConnection, this.metadataBackend, - this.userLimitsApi, + this.userLimitsBackend, this.mapConfigAdapter, this.affectedTablesCache, user, diff --git a/lib/cartodb/models/mapconfig/adapter/mapconfig-overviews-adapter.js b/lib/cartodb/models/mapconfig/adapter/mapconfig-overviews-adapter.js index 72c29593..a104c592 100644 --- a/lib/cartodb/models/mapconfig/adapter/mapconfig-overviews-adapter.js +++ b/lib/cartodb/models/mapconfig/adapter/mapconfig-overviews-adapter.js @@ -2,9 +2,9 @@ var step = require('step'); var queue = require('queue-async'); var _ = require('underscore'); -function MapConfigOverviewsAdapter(overviewsMetadataApi, filterStatsApi) { - this.overviewsMetadataApi = overviewsMetadataApi; - this.filterStatsApi = filterStatsApi; +function MapConfigOverviewsAdapter(overviewsMetadataBackend, filterStatsBackend) { + this.overviewsMetadataBackend = overviewsMetadataBackend; + this.filterStatsBackend = filterStatsBackend; } module.exports = MapConfigOverviewsAdapter; @@ -25,7 +25,7 @@ MapConfigOverviewsAdapter.prototype.getMapConfig = function(user, requestMapConf if ( layer.type !== 'mapnik' && layer.type !== 'cartodb' ) { return done(null, layer); } - self.overviewsMetadataApi.getOverviewsMetadata(user, layer.options.sql, function(err, metadata){ + self.overviewsMetadataBackend.getOverviewsMetadata(user, layer.options.sql, function(err, metadata){ if (err) { done(err, layer); } else { @@ -53,7 +53,7 @@ MapConfigOverviewsAdapter.prototype.getMapConfig = function(user, requestMapConf function collectStatsData(err, filters, unfiltered_query) { var next_step = this; if ( filters ) { - self.filterStatsApi.getFilterStats( + self.filterStatsBackend.getFilterStats( user, unfiltered_query, filters, function(err, stats) { diff --git a/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js b/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js index 1f19d395..bc36d3ae 100644 --- a/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js +++ b/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js @@ -7,16 +7,23 @@ const QueryTables = require('cartodb-query-tables'); /** * @param {MapConfig} mapConfig * @param {String} user - * @param {UserLimitsApi} userLimitsApi + * @param {UserLimitsBackend} userLimitsBackend * @param {Object} params * @constructor * @type {CreateLayergroupMapConfigProvider} */ -function CreateLayergroupMapConfigProvider(mapConfig, user, userLimitsApi, pgConnection, affectedTablesCache, params) { +function CreateLayergroupMapConfigProvider( + mapConfig, + user, + userLimitsBackend, + pgConnection, + affectedTablesCache, + params +) { this.mapConfig = mapConfig; this.user = user; - this.userLimitsApi = userLimitsApi; + this.userLimitsBackend = userLimitsBackend; this.pgConnection = pgConnection; this.affectedTablesCache = affectedTablesCache; this.params = params; @@ -36,7 +43,7 @@ CreateLayergroupMapConfigProvider.prototype.getMapConfig = function(callback) { step( function prepareContextLimits() { - self.userLimitsApi.getRenderLimits(self.user, self.params.api_key, this); + self.userLimitsBackend.getRenderLimits(self.user, self.params.api_key, this); }, function handleRenderLimits(err, renderLimits) { assert.ifError(err); diff --git a/lib/cartodb/models/mapconfig/provider/map-store-provider.js b/lib/cartodb/models/mapconfig/provider/map-store-provider.js index d9f9da83..1fd9dadf 100644 --- a/lib/cartodb/models/mapconfig/provider/map-store-provider.js +++ b/lib/cartodb/models/mapconfig/provider/map-store-provider.js @@ -7,15 +7,15 @@ const QueryTables = require('cartodb-query-tables'); /** * @param {MapStore} mapStore * @param {String} user - * @param {UserLimitsApi} userLimitsApi + * @param {UserLimitsBackend} userLimitsBackend * @param {Object} params * @constructor * @type {MapStoreMapConfigProvider} */ -function MapStoreMapConfigProvider(mapStore, user, userLimitsApi, pgConnection, affectedTablesCache, params) { +function MapStoreMapConfigProvider(mapStore, user, userLimitsBackend, pgConnection, affectedTablesCache, params) { this.mapStore = mapStore; this.user = user; - this.userLimitsApi = userLimitsApi; + this.userLimitsBackend = userLimitsBackend; this.pgConnection = pgConnection; this.affectedTablesCache = affectedTablesCache; this.token = params.token; @@ -38,7 +38,7 @@ MapStoreMapConfigProvider.prototype.getMapConfig = function(callback) { step( function prepareContextLimits() { - self.userLimitsApi.getRenderLimits(self.user, self.params.api_key, this); + self.userLimitsBackend.getRenderLimits(self.user, self.params.api_key, this); }, function handleRenderLimits(err, renderLimits) { assert.ifError(err); diff --git a/lib/cartodb/models/mapconfig/provider/named-map-provider.js b/lib/cartodb/models/mapconfig/provider/named-map-provider.js index 065d20f4..2d9a88c2 100644 --- a/lib/cartodb/models/mapconfig/provider/named-map-provider.js +++ b/lib/cartodb/models/mapconfig/provider/named-map-provider.js @@ -15,7 +15,7 @@ function NamedMapMapConfigProvider( templateMaps, pgConnection, metadataBackend, - userLimitsApi, + userLimitsBackend, mapConfigAdapter, affectedTablesCache, owner, @@ -27,7 +27,7 @@ function NamedMapMapConfigProvider( this.templateMaps = templateMaps; this.pgConnection = pgConnection; this.metadataBackend = metadataBackend; - this.userLimitsApi = userLimitsApi; + this.userLimitsBackend = userLimitsBackend; this.mapConfigAdapter = mapConfigAdapter; this.owner = owner; @@ -125,7 +125,7 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) { function prepareContextLimits(err, _mapConfig) { assert.ifError(err); mapConfig = _mapConfig; - self.userLimitsApi.getRenderLimits(self.owner, self.params.api_key, this); + self.userLimitsBackend.getRenderLimits(self.owner, self.params.api_key, this); }, function cacheAndReturnMapConfig(err, renderLimits) { self.err = err; diff --git a/lib/cartodb/controllers/server-info.js b/lib/cartodb/server-info-controller.js similarity index 96% rename from lib/cartodb/controllers/server-info.js rename to lib/cartodb/server-info-controller.js index 12f6432b..17e0649c 100644 --- a/lib/cartodb/controllers/server-info.js +++ b/lib/cartodb/server-info-controller.js @@ -1,4 +1,4 @@ -var HealthCheck = require('../monitoring/health_check'); +var HealthCheck = require('./monitoring/health_check'); var WELCOME_MSG = "This is the CartoDB Maps API, " + "see the documentation at http://docs.cartodb.com/cartodb-platform/maps-api.html"; diff --git a/lib/cartodb/server.js b/lib/cartodb/server.js index ab6fcc62..ea51f2db 100644 --- a/lib/cartodb/server.js +++ b/lib/cartodb/server.js @@ -5,8 +5,8 @@ const { mapnik } = windshaft; const jsonReplacer = require('./utils/json-replacer'); -const ApiRouter = require('./controllers/api-router'); -const ServerInfoController = require('./controllers/server-info'); +const ApiRouter = require('./api/api-router'); +const ServerInfoController = require('./server-info-controller'); const StatsClient = require('./stats/client'); diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index adc03003..c3d0fdb8 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -67,6 +67,52 @@ module.exports = { // FIXME: Remove it. This is no longer needed, paths are defined in routers base_url_templated: global.environment.base_url_templated || '(?:/maps/named|/tiles/template)', + // Base URLs for the APIs + // + // See http://github.com/CartoDB/Windshaft-cartodb/wiki/Unified-Map-API + routes: global.environment.routes || { + v1: { + 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' + ], + // Base url for the Detached Maps API + // "/tiles/layergroup" is for compatibility with versions up to 1.6.x + map: { + paths: [ + '/layergroup' + ] + }, + // Base url for the Templated Maps API + // "/tiles/template" is for compatibility with versions up to 1.6.x + template: { + paths: [ + '/template' + ] + } + } + }, + grainstore: { map: { // TODO: allow to specify in configuration diff --git a/test/acceptance/ported/support/ported_server_options.js b/test/acceptance/ported/support/ported_server_options.js index 1ce262af..243875a0 100644 --- a/test/acceptance/ported/support/ported_server_options.js +++ b/test/acceptance/ported/support/ported_server_options.js @@ -11,6 +11,31 @@ module.exports = _.extend({}, serverOptions, { base_url: '/database/:dbname/table/:table', // FIXME: Remove it. This is no longer needed, paths are defined in routers base_url_mapconfig: '/database/:dbname/layergroup', + + routes: { + v0: { + paths: [ + '/tiles', + '/database/:dbname' + ], + // Base url for the Detached Maps API + // "/tiles/layergroup" is for compatibility with versions up to 1.6.x + map: { + paths: [ + '/layergroup' + ] + }, + // Base url for the Templated Maps API + // "/tiles/template" is for compatibility with versions up to 1.6.x + template: { + paths: [ + '/template' + ] + } + } + }, + + grainstore: { datasource: { geometry_field: 'the_geom', diff --git a/test/acceptance/rate-limit.test.js b/test/acceptance/rate-limit.test.js index eb9f8954..925d5028 100644 --- a/test/acceptance/rate-limit.test.js +++ b/test/acceptance/rate-limit.test.js @@ -5,11 +5,11 @@ const redis = require('redis'); const RedisPool = require('redis-mpool'); const cartodbRedis = require('cartodb-redis'); const TestClient = require('../support/test-client'); -const UserLimitsApi = require('../../lib/cartodb/api/user_limits_api'); -const rateLimitMiddleware = require('../../lib/cartodb/middleware/rate-limit'); +const UserLimitsBackend = require('../../lib/cartodb/backends/user-limits'); +const rateLimitMiddleware = require('../../lib/cartodb/api/middlewares/rate-limit'); const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimitMiddleware; -let userLimitsApi; +let userLimitsApi; let rateLimit; let redisClient; let testClient; @@ -112,11 +112,11 @@ function assertGetLayergroupRequest (status, limit, remaining, reset, retry, don 'Carto-Rate-Limit-Reset': reset } }; - + if(retry) { response.headers['Retry-After'] = retry; } - + testClient.getLayergroup({ response }, err => { assert.ifError(err); if (done) { @@ -133,11 +133,11 @@ function assertRateLimitRequest (status, limit, remaining, reset, retry, done) { "Carto-Rate-Limit-Remaining": remaining, "Carto-Rate-Limit-Reset": reset }; - + if(retry) { expectedHeaders['Retry-After'] = retry; } - + assert.deepEqual(res.headers, expectedHeaders); if(status === 200) { @@ -160,7 +160,7 @@ describe('rate limit', function() { before(function() { global.environment.enabledFeatures.rateLimitsEnabled = true; global.environment.enabledFeatures.rateLimitsByEndpoint.anonymous = true; - + redisClient = redis.createClient(global.environment.redis.port); testClient = new TestClient(createMapConfig(), 1234); }); @@ -183,7 +183,7 @@ describe('rate limit', function() { done(); }); }); - }); + }); it('should not be rate limited', function (done) { const count = 1; @@ -218,7 +218,7 @@ describe('rate limit middleware', function () { const redisPool = new RedisPool(global.environment.redis); const metadataBackend = cartodbRedis({ pool: redisPool }); - userLimitsApi = new UserLimitsApi(metadataBackend, { + userLimitsApi = new UserLimitsBackend(metadataBackend, { limits: { rateLimitsEnabled: global.environment.enabledFeatures.rateLimitsEnabled } @@ -257,9 +257,9 @@ describe('rate limit middleware', function () { it("1 req/sec: 2 req/seg should be limited, removing SHA script from Redis", function (done) { userLimitsApi.metadataBackend.redisCmd( - 8, - 'SCRIPT', - ['FLUSH'], + 8, + 'SCRIPT', + ['FLUSH'], function () { assertRateLimitRequest(200, 1, 0, 1); setTimeout( () => assertRateLimitRequest(429, 1, 0, 0, 1), 500); @@ -277,7 +277,7 @@ describe('rate limit and vector tiles', function () { before(function(done) { global.environment.enabledFeatures.rateLimitsEnabled = true; global.environment.enabledFeatures.rateLimitsByEndpoint.tile = true; - + redisClient = redis.createClient(global.environment.redis.port); const count = 1; const period = 1; @@ -287,9 +287,9 @@ describe('rate limit and vector tiles', function () { testClient = new TestClient(createMapConfig(), 1234); testClient.getLayergroup({status: 200}, (err, res) => { assert.ifError(err); - + layergroupid = res.layergroupid; - + done(); }); }); @@ -336,12 +336,12 @@ describe('rate limit and vector tiles', function () { testClient.getTile(0, 0, 0, tileParams(204, '1', '0', '1'), (err) => { assert.ifError(err); - + testClient.getTile( - 0, - 0, - 0, - tileParams(429, '1', '0', '0', '1', 'application/x-protobuf'), + 0, + 0, + 0, + tileParams(429, '1', '0', '0', '1', 'application/x-protobuf'), (err, res, tile) => { assert.ifError(err); @@ -350,11 +350,11 @@ describe('rate limit and vector tiles', function () { assert.equal(tileJSON.length, 2); assert.equal(tileJSON[0].name, 'errorTileSquareLayer'); assert.equal(tileJSON[1].name, 'errorTileStripesLayer'); - + done(); } - ); + ); }); - + }); }); diff --git a/test/integration/mapconfig_overviews_adapter.js b/test/integration/mapconfig_overviews_adapter.js index 87a87935..d5414a7e 100644 --- a/test/integration/mapconfig_overviews_adapter.js +++ b/test/integration/mapconfig_overviews_adapter.js @@ -5,18 +5,18 @@ var RedisPool = require('redis-mpool'); var cartodbRedis = require('cartodb-redis'); var PgConnection = require(__dirname + '/../../lib/cartodb/backends/pg_connection'); var PgQueryRunner = require('../../lib/cartodb/backends/pg_query_runner'); -var OverviewsMetadataApi = require('../../lib/cartodb/api/overviews_metadata_api'); -var FilterStatsApi = require('../../lib/cartodb/api/filter_stats_api'); +var OverviewsMetadataBackend = require('../../lib/cartodb/backends/overviews-metadata'); +var FilterStatsBackend = require('../../lib/cartodb/backends/filter-stats'); var MapConfigOverviewsAdapter = require('../../lib/cartodb/models/mapconfig/adapter/mapconfig-overviews-adapter'); var redisPool = new RedisPool(global.environment.redis); var metadataBackend = cartodbRedis({pool: redisPool}); var pgConnection = new PgConnection(metadataBackend); var pgQueryRunner = new PgQueryRunner(pgConnection); -var overviewsMetadataApi = new OverviewsMetadataApi(pgQueryRunner); -var filterStatsApi = new FilterStatsApi(pgQueryRunner); +var overviewsMetadataBackend = new OverviewsMetadataBackend(pgQueryRunner); +var filterStatsBackend = new FilterStatsBackend(pgQueryRunner); -var mapConfigOverviewsAdapter = new MapConfigOverviewsAdapter(overviewsMetadataApi, filterStatsApi); +var mapConfigOverviewsAdapter = new MapConfigOverviewsAdapter(overviewsMetadataBackend, filterStatsBackend); describe('MapConfigOverviewsAdapter', function() { diff --git a/test/integration/overviews-metadata-api.js b/test/integration/overviews-metadata-api.js index 4d015870..ce82a1d9 100644 --- a/test/integration/overviews-metadata-api.js +++ b/test/integration/overviews-metadata-api.js @@ -7,24 +7,24 @@ var cartodbRedis = require('cartodb-redis'); var PgConnection = require('../../lib/cartodb/backends/pg_connection'); var PgQueryRunner = require('../../lib/cartodb/backends/pg_query_runner'); -var OverviewsMetadataApi = require('../../lib/cartodb/api/overviews_metadata_api'); +var OverviewsMetadataBackend = require('../../lib/cartodb/backends/overviews-metadata'); -describe('OverviewsMetadataApi', function() { +describe('OverviewsMetadataBackend', function() { - var overviewsMetadataApi; + var overviewsMetadataBackend; before(function() { var redisPool = new RedisPool(global.environment.redis); var metadataBackend = cartodbRedis({pool: redisPool}); var pgConnection = new PgConnection(metadataBackend); var pgQueryRunner = new PgQueryRunner(pgConnection); - overviewsMetadataApi = new OverviewsMetadataApi(pgQueryRunner); + overviewsMetadataBackend = new OverviewsMetadataBackend(pgQueryRunner); }); it('should return an empty relation for tables that have no overviews', function(done) { var query = 'select * from test_table'; - overviewsMetadataApi.getOverviewsMetadata('localhost', query, function(err, result) { + overviewsMetadataBackend.getOverviewsMetadata('localhost', query, function(err, result) { assert.ok(!err, err); assert.deepEqual(result, {}); @@ -35,7 +35,7 @@ describe('OverviewsMetadataApi', function() { it('should return overviews metadata', function(done) { var query = 'select * from test_table_overviews'; - overviewsMetadataApi.getOverviewsMetadata('localhost', query, function(err, result) { + overviewsMetadataBackend.getOverviewsMetadata('localhost', query, function(err, result) { assert.ok(!err, err); assert.deepEqual(result, { diff --git a/test/unit/cartodb/error-middleware.test.js b/test/unit/cartodb/error-middleware.test.js index 861bec54..88b1ed6e 100644 --- a/test/unit/cartodb/error-middleware.test.js +++ b/test/unit/cartodb/error-middleware.test.js @@ -1,7 +1,7 @@ require('../../support/test_helper.js'); var assert = require('assert'); -var errorMiddleware = require('../../../lib/cartodb/middleware/error-middleware'); +var errorMiddleware = require('../../../lib/cartodb/api/middlewares/error-middleware'); describe('error-middleware', function() { @@ -28,7 +28,7 @@ describe('error-middleware', function() { error.subtype = 'test subtype'; const errors = [error, error]; - + const req = {}; const res = { headers: {}, @@ -43,7 +43,7 @@ describe('error-middleware', function() { send () {} }; - const errorHeader = { + const errorHeader = { mainError: { statusCode: 400, message: error.message, @@ -133,7 +133,7 @@ describe('error-middleware', function() { error.subtype = badString; const errors = [error, error]; - + const req = {}; const res = { headers: {}, @@ -148,7 +148,7 @@ describe('error-middleware', function() { send () {} }; - const errorHeader = { + const errorHeader = { mainError: { statusCode: 400, message: escapedString, diff --git a/test/unit/cartodb/error_messages.test.js b/test/unit/cartodb/error_messages.test.js index bfe0b03a..ecc6fe3c 100644 --- a/test/unit/cartodb/error_messages.test.js +++ b/test/unit/cartodb/error_messages.test.js @@ -2,7 +2,7 @@ require('../../support/test_helper'); var assert = require('assert'); -var errorMiddleware = require('../../../lib/cartodb/middleware/error-middleware'); +var errorMiddleware = require('../../../lib/cartodb/api/middlewares/error-middleware'); describe('error messages clean up', function() { diff --git a/test/unit/cartodb/lzmaMiddleware.test.js b/test/unit/cartodb/lzmaMiddleware.test.js index 3ad81962..9701d7ca 100644 --- a/test/unit/cartodb/lzmaMiddleware.test.js +++ b/test/unit/cartodb/lzmaMiddleware.test.js @@ -1,7 +1,7 @@ var assert = require('assert'); var testHelper = require('../../support/test_helper'); -var lzmaMiddleware = require('../../../lib/cartodb/middleware/lzma'); +var lzmaMiddleware = require('../../../lib/cartodb/api/middlewares/lzma'); describe('lzma-middleware', function() { diff --git a/test/unit/cartodb/middlewares/coordinates.test.js b/test/unit/cartodb/middlewares/coordinates.test.js index 11cd2626..5b60aa82 100644 --- a/test/unit/cartodb/middlewares/coordinates.test.js +++ b/test/unit/cartodb/middlewares/coordinates.test.js @@ -1,5 +1,5 @@ const assert = require('assert'); -const coordinates = require('../../../../lib/cartodb/middleware/coordinates'); +const coordinates = require('../../../../lib/cartodb/api/middlewares/coordinates'); describe('coordinates middleware', function () { it('should return error: invalid zoom paramenter (-1)', function (done) { diff --git a/test/unit/cartodb/prepare-context.test.js b/test/unit/cartodb/prepare-context.test.js index ff311cc6..02b63dc7 100644 --- a/test/unit/cartodb/prepare-context.test.js +++ b/test/unit/cartodb/prepare-context.test.js @@ -4,13 +4,13 @@ var _ = require('underscore'); var RedisPool = require('redis-mpool'); var cartodbRedis = require('cartodb-redis'); var PgConnection = require('../../../lib/cartodb/backends/pg_connection'); -var AuthApi = require('../../../lib/cartodb/api/auth_api'); +var AuthBackend = require('../../../lib/cartodb/backends/auth'); var TemplateMaps = require('../../../lib/cartodb/backends/template_maps'); -const cleanUpQueryParamsMiddleware = require('../../../lib/cartodb/middleware/clean-up-query-params'); -const authorizeMiddleware = require('../../../lib/cartodb/middleware/authorize'); -const dbConnSetupMiddleware = require('../../../lib/cartodb/middleware/db-conn-setup'); -const credentialsMiddleware = require('../../../lib/cartodb/middleware/credentials'); +const cleanUpQueryParamsMiddleware = require('../../../lib/cartodb/api/middlewares/clean-up-query-params'); +const authorizeMiddleware = require('../../../lib/cartodb/api/middlewares/authorize'); +const dbConnSetupMiddleware = require('../../../lib/cartodb/api/middlewares/db-conn-setup'); +const credentialsMiddleware = require('../../../lib/cartodb/api/middlewares/credentials'); var windshaft = require('windshaft'); @@ -31,10 +31,10 @@ describe('prepare-context', function() { var metadataBackend = cartodbRedis({pool: redisPool}); var pgConnection = new PgConnection(metadataBackend); var templateMaps = new TemplateMaps(redisPool); - var authApi = new AuthApi(pgConnection, metadataBackend, mapStore, templateMaps); + var authBackend = new AuthBackend(pgConnection, metadataBackend, mapStore, templateMaps); cleanUpQueryParams = cleanUpQueryParamsMiddleware(); - authorize = authorizeMiddleware(authApi); + authorize = authorizeMiddleware(authBackend); dbConnSetup = dbConnSetupMiddleware(pgConnection); setCredentials = credentialsMiddleware(); });