From c77ea495946229afca3a68c7eaac5ad5506d0bb4 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Thu, 5 May 2016 17:52:37 +0200 Subject: [PATCH] Use a more aggressive cache control header for node status endpoint --- lib/cartodb/controllers/layergroup.js | 5 +- test/acceptance/analysis/analysis-layers.js | 23 ++++++ test/support/test-client.js | 89 +++++++++++++++++++++ 3 files changed, 116 insertions(+), 1 deletion(-) diff --git a/lib/cartodb/controllers/layergroup.js b/lib/cartodb/controllers/layergroup.js index 99eca0c5..1c79e47a 100644 --- a/lib/cartodb/controllers/layergroup.js +++ b/lib/cartodb/controllers/layergroup.js @@ -116,7 +116,10 @@ LayergroupController.prototype.analysisNodeStatus = function(req, res) { if (err) { self.sendError(req, res, err, 'GET NODE STATUS'); } else { - self.sendResponse(req, res, nodeStatus, 200); + self.sendResponse(req, res, nodeStatus, 200, { + 'Cache-Control': 'public,max-age=5', + 'Last-Modified': new Date().toUTCString() + }); } } ); diff --git a/test/acceptance/analysis/analysis-layers.js b/test/acceptance/analysis/analysis-layers.js index 52a617d9..826c6604 100644 --- a/test/acceptance/analysis/analysis-layers.js +++ b/test/acceptance/analysis/analysis-layers.js @@ -304,4 +304,27 @@ describe('analysis-layers', function() { testClient.drain(done); }); }); + + it('should response with custom cache headers for node status endpoints', function(done) { + var useCase = useCases[1]; + + // No API key here + var testClient = new TestClient(useCase.mapConfig, 1234); + + testClient.getNodeStatus('HEAD', function(err, response, nodeStatus) { + assert.ok(!err, err); + + assert.equal(nodeStatus.status, 'ready'); + + var headers = response.headers; + + assert.equal(headers['cache-control'], 'public,max-age=5'); + + var lastModified = new Date(headers['last-modified']); + var tenSecondsInMs = 1e5; + assert.ok(Date.now() - lastModified.getTime() < tenSecondsInMs); + + testClient.drain(done); + }); + }); }); diff --git a/test/support/test-client.js b/test/support/test-client.js index 2d6213f6..5ced9f98 100644 --- a/test/support/test-client.js +++ b/test/support/test-client.js @@ -2,6 +2,7 @@ var qs = require('querystring'); var step = require('step'); +var urlParser = require('url'); var mapnik = require('windshaft').mapnik; @@ -379,6 +380,94 @@ TestClient.prototype.getLayergroup = function(expectedResponse, callback) { ); }; +TestClient.prototype.getNodeStatus = function(nodeName, callback) { + var self = this; + + var url = '/api/v1/map'; + + if (this.apiKey) { + url += '?' + qs.stringify({api_key: this.apiKey}); + } + + var layergroupId; + var nodes = {}; + step( + function createLayergroup() { + var next = this; + assert.response(server, + { + url: url, + method: 'POST', + headers: { + host: 'localhost', + 'Content-Type': 'application/json' + }, + data: JSON.stringify(self.mapConfig) + }, + { + status: 200, + headers: { + 'Content-Type': 'application/json; charset=utf-8' + } + }, + function(res, err) { + if (err) { + return next(err); + } + var parsedBody = JSON.parse(res.body); + + nodes = parsedBody.metadata.analyses.reduce(function(nodes, analysis) { + return Object.keys(analysis.nodes).reduce(function(nodes, nodeName) { + var node = analysis.nodes[nodeName]; + nodes[nodeName] = node.url.http; + return nodes; + }, nodes); + }, nodes); + + return next(null, parsedBody.layergroupid); + } + ); + }, + function getNodeStatusResult(err, _layergroupId) { + assert.ifError(err); + + var next = this; + layergroupId = _layergroupId; + + url = urlParser.parse(nodes[nodeName]).path; + + if (self.apiKey) { + url += '?' + qs.stringify({api_key: self.apiKey}); + } + + var request = { + url: url, + method: 'GET', + headers: { + host: 'localhost' + } + }; + + var expectedResponse = { + status: 200, + headers: { + 'Content-Type': 'application/json; charset=utf-8' + } + }; + + assert.response(server, request, expectedResponse, function(res, err) { + assert.ifError(err); + next(null, res, JSON.parse(res.body)); + }); + }, + function finish(err, res, image) { + self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0; + self.keysToDelete['user:localhost:mapviews:global'] = 5; + return callback(err, res, image); + } + ); +}; + TestClient.prototype.drain = function(callback) { helper.deleteRedisKeys(this.keysToDelete, callback); };