From adeffd20183ea87742fa54d7437645eb3e50b883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Thu, 4 Jun 2020 17:45:15 +0200 Subject: [PATCH] Centralize common headers, this will help up to move biz metrics out of the process --- lib/api/map/preview-template-controller.js | 6 +- lib/api/middlewares/error-middleware.js | 28 ++-- .../middlewares/increment-map-view-count.js | 5 - lib/api/middlewares/send-response.js | 28 ++-- lib/api/middlewares/user.js | 2 +- lib/utils/common-headers.js | 127 ++++++++++++++++++ 6 files changed, 162 insertions(+), 34 deletions(-) create mode 100644 lib/utils/common-headers.js diff --git a/lib/api/map/preview-template-controller.js b/lib/api/map/preview-template-controller.js index 287c0122..dc960510 100644 --- a/lib/api/map/preview-template-controller.js +++ b/lib/api/map/preview-template-controller.js @@ -346,11 +346,9 @@ function incrementMapViews ({ metadataBackend }) { return next(); } - const statTag = mapConfig.obj().stat_tag; + res.locals.mapConfig = mapConfig; - if (statTag) { - res.set('Carto-Stat-Tag', `${statTag}`); - } + const statTag = mapConfig.obj().stat_tag; metadataBackend.incMapviewCount(user, statTag, (err) => { if (err) { diff --git a/lib/api/middlewares/error-middleware.js b/lib/api/middlewares/error-middleware.js index faca863f..9994a754 100644 --- a/lib/api/middlewares/error-middleware.js +++ b/lib/api/middlewares/error-middleware.js @@ -1,5 +1,7 @@ 'use strict'; +const setCommonHeaders = require('../../utils/common-headers'); + module.exports = function errorMiddleware (/* options */) { return function error (err, req, res, next) { const { logger } = res.locals; @@ -7,21 +9,23 @@ module.exports = function errorMiddleware (/* options */) { logger.error({ error: errors }); - const errorResponseBody = { - errors: errors.map(errorMessage), - errors_with_context: errors.map(errorMessageWithContext) - }; + setCommonHeaders(req, res, () => { + const errorResponseBody = { + errors: errors.map(errorMessage), + errors_with_context: errors.map(errorMessageWithContext) + }; - // If a callback was requested, force status to 200 - res.status(req.query.callback ? 200 : findStatusCode(errors[0])); + // If a callback was requested, force status to 200 + res.status(req.query.callback ? 200 : findStatusCode(errors[0])); - if (req.query && req.query.callback) { - res.jsonp(errorResponseBody); - } else { - res.json(errorResponseBody); - } + if (req.query && req.query.callback) { + res.jsonp(errorResponseBody); + } else { + res.json(errorResponseBody); + } - return next(); + return next(); + }); }; }; diff --git a/lib/api/middlewares/increment-map-view-count.js b/lib/api/middlewares/increment-map-view-count.js index c226d1d6..fb8bdacd 100644 --- a/lib/api/middlewares/increment-map-view-count.js +++ b/lib/api/middlewares/increment-map-view-count.js @@ -5,11 +5,6 @@ module.exports = function incrementMapViewCount (metadataBackend) { const { mapConfig, user, logger } = res.locals; const statTag = mapConfig.obj().stat_tag; - if (statTag) { - res.set('Carto-Stat-Tag', `${statTag}`); - } - - // Error won't blow up, just be logged. metadataBackend.incMapviewCount(user, statTag, (err) => { if (err) { err.message = `Failed to increment mapview count for user '${user}'. ${err.message}`; diff --git a/lib/api/middlewares/send-response.js b/lib/api/middlewares/send-response.js index d65d7597..f2328d6f 100644 --- a/lib/api/middlewares/send-response.js +++ b/lib/api/middlewares/send-response.js @@ -1,20 +1,24 @@ 'use strict'; +const setCommonHeaders = require('../../utils/common-headers'); + module.exports = function sendResponse () { return function sendResponseMiddleware (req, res, next) { - res.status(res.statusCode); + setCommonHeaders(req, res, () => { + res.status(res.statusCode); - if (Buffer.isBuffer(res.body)) { - res.send(res.body); + if (Buffer.isBuffer(res.body)) { + res.send(res.body); + return next(); + } + + if (req.query.callback) { + res.jsonp(res.body); + return next(); + } + + res.json(res.body); return next(); - } - - if (req.query.callback) { - res.jsonp(res.body); - return next(); - } - - res.json(res.body); - return next(); + }); }; }; diff --git a/lib/api/middlewares/user.js b/lib/api/middlewares/user.js index 814b62e6..bf508085 100644 --- a/lib/api/middlewares/user.js +++ b/lib/api/middlewares/user.js @@ -18,7 +18,7 @@ module.exports = function user (metadataBackend) { } res.locals.userId = userId; - res.set('Carto-User-Id', `${userId}`); + return next(); }); }; diff --git a/lib/utils/common-headers.js b/lib/utils/common-headers.js new file mode 100644 index 00000000..a0d20765 --- /dev/null +++ b/lib/utils/common-headers.js @@ -0,0 +1,127 @@ +'use strict'; + +module.exports = function setCommonHeaders (req, res, callback) { + const { logger } = res.locals; + + res.set('X-Request-Id', logger.bindings.id); + + // TODO: x-layergroupid header?? + + const user = getUser({ res }); + + if (user) { + res.set('Carto-User', user); + } + + const userId = getUserId({ res }); + + if (userId) { + res.set('Carto-User-Id', `${userId}`); + } + + const mapId = getMapId({ res }); + + if (mapId) { + res.set('Carto-Map-Id', mapId); + } + + const cacheBuster = getCacheBuster({ res }); + + if (cacheBuster) { + res.set('Carto-Cache-Buster', cacheBuster); + } + + const templateHash = getTemplateHash({ res }); + + if (templateHash) { + res.set('Carto-Template-Hash', templateHash); + } + + getStatTag({ res }, (err, statTag) => { + if (err) { + err.message = `Error generating Stat Tag header: ${err.message}`; + logger.warn({ error: err }); + } + + if (statTag) { + res.set('Carto-Stat-Tag', statTag); + } + + callback(); + }); +}; + +function getUser ({ res }) { + if (res.locals.user) { + return res.locals.user; + } +} + +function getUserId ({ res }) { + if (res.locals.userId) { + return res.locals.userId; + } +} + +function getMapId ({ res }) { + if (res.locals.token) { + return res.locals.token; + } + + if (res.locals.mapConfig) { + return res.locals.mapConfig.id(); + } + + if (res.locals.mapConfigProvider && res.locals.mapConfigProvider.mapConfig) { + return res.locals.mapConfigProvider.mapConfig.id(); + } +} + +function getCacheBuster ({ res }) { + if (res.locals.cache_buster !== undefined) { + return `${res.locals.cache_buster}`; + } + + if (res.locals.mapConfigProvider) { + return `${res.locals.mapConfigProvider.getCacheBuster()}`; + } +} + +function getTemplateHash ({ res }) { + const { logger } = res.locals; + + if (res.locals.templateHash) { + return res.locals.templateHash; + } + + if (res.locals.mapConfigProvider && typeof res.locals.mapConfigProvider.getTemplateHash === 'function') { + let templateHash; + + try { + templateHash = res.locals.mapConfigProvider.getTemplateHash().substring(0, 8); + } catch (err) { + err.message = `Error generating Stat Tag header: ${err.message}`; + logger.warn({ error: err }); + } + + return templateHash; + } +} + +function getStatTag ({ res }, callback) { + if (res.locals.mapConfig) { + return callback(null, res.locals.mapConfig.obj().stat_tag); + } + + if (!res.locals.mapConfigProvider) { + return callback(); + } + + res.locals.mapConfigProvider.getMapConfig((err, mapConfig) => { + if (err) { + return callback(err); + } + + return callback(null, mapConfig.obj().stat_tag); + }); +}