From 2ee94118894cfa4812c63785ef4660200ee9eb0f Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Mon, 22 Jul 2013 17:21:38 +0200 Subject: [PATCH] Review cache-control headers: * Raise max-age to one year for all cacheable queries * Set max-age to 0 for uncacheable (mutating) queries --- NEWS.md | 2 ++ app/controllers/app.js | 12 +++++++---- test/acceptance/app.test.js | 42 +++++++++++++++++++------------------ 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/NEWS.md b/NEWS.md index d70be409..34e47910 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,8 @@ 1.5.3 ----- * Set Last-Modified header with cache_policy=persist +* Raise max-age to one year for all cacheable queries +* Set max-age to 0 for uncacheable (mutating) queries 1.5.2 ----- diff --git a/app/controllers/app.js b/app/controllers/app.js index d846e5da..15d2a8af 100755 --- a/app/controllers/app.js +++ b/app/controllers/app.js @@ -257,13 +257,17 @@ function handleQuery(req, res) { setCrossDomain(res); // set cache headers - res.header('X-Cache-Channel', generateCacheKey(database, tableCacheItem, authenticated)); + var ttl = 31536000; // 1 year time to live by default var cache_policy = req.query.cache_policy; if ( cache_policy == 'persist' ) { - res.header('Cache-Control', 'public,max-age=31536000'); // 1 year + res.header('Cache-Control', 'public,max-age=' + ttl); + res.header('X-Cache-Channel', ''); // forever } else { - // TODO: set ttl=0 when tableCache[sql_md5].may_write is true ? - var ttl = 3600; + if ( tableCacheItem.may_write ) { + ttl = 0; + } else { + res.header('X-Cache-Channel', generateCacheKey(database, tableCacheItem, authenticated)); + } res.header('Cache-Control', 'no-cache,max-age='+ttl+',must-revalidate,public'); } diff --git a/test/acceptance/app.test.js b/test/acceptance/app.test.js index 8ffcb1e8..0913af84 100644 --- a/test/acceptance/app.test.js +++ b/test/acceptance/app.test.js @@ -30,7 +30,8 @@ app.setMaxListeners(0); suite('app.test', function() { -var expected_cache_control = 'no-cache,max-age=3600,must-revalidate,public'; +var expected_cache_control = 'no-cache,max-age=31536000,must-revalidate,public'; +var expected_rw_cache_control = 'no-cache,max-age=0,must-revalidate,public'; var expected_cache_control_persist = 'public,max-age=31536000'; test('GET /api/v1/sql', function(done){ @@ -114,7 +115,8 @@ test('cache_policy=persist', function(done){ assert.equal(res.statusCode, 200, res.body); // Check cache headers // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/43 - assert.equal(res.headers['x-cache-channel'], 'cartodb_test_user_1_db:untitle_table_4'); + assert.ok(res.headers.hasOwnProperty('x-cache-channel')); + assert.equal(res.headers['x-cache-channel'], ''); assert.equal(res.headers['cache-control'], expected_cache_control_persist); done(); }); @@ -243,8 +245,8 @@ test('INSERT returns affected rows', function(done){ assert.equal(out.rows.length, 0); // Check cache headers // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/43 - assert.equal(res.headers['x-cache-channel'], 'NONE'); - assert.equal(res.headers['cache-control'], expected_cache_control); + assert.ok(!res.hasOwnProperty('x-cache-channel')); + assert.equal(res.headers['cache-control'], expected_rw_cache_control); done(); }); }); @@ -269,8 +271,8 @@ test('UPDATE returns affected rows', function(done){ assert.equal(out.rows.length, 0); // Check cache headers // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/43 - assert.equal(res.headers['x-cache-channel'], 'NONE'); - assert.equal(res.headers['cache-control'], expected_cache_control); + assert.ok(!res.hasOwnProperty('x-cache-channel')); + assert.equal(res.headers['cache-control'], expected_rw_cache_control); done(); }); }); @@ -295,8 +297,8 @@ test('DELETE returns affected rows', function(done){ assert.equal(out.rows.length, 0); // Check cache headers // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/43 - assert.equal(res.headers['x-cache-channel'], 'NONE'); - assert.equal(res.headers['cache-control'], expected_cache_control); + assert.ok(!res.hasOwnProperty('x-cache-channel')); + assert.equal(res.headers['cache-control'], expected_rw_cache_control); done(); }); }); @@ -422,8 +424,8 @@ test('CREATE TABLE with GET and auth', function(done){ assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); // Check cache headers // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/43 - assert.equal(res.headers['x-cache-channel'], 'NONE'); - assert.equal(res.headers['cache-control'], expected_cache_control); + assert.ok(!res.hasOwnProperty('x-cache-channel')); + assert.equal(res.headers['cache-control'], expected_rw_cache_control); done(); }); }); @@ -478,8 +480,8 @@ test('ALTER TABLE with GET and auth', function(done){ assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); // Check cache headers // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/43 - assert.equal(res.headers['x-cache-channel'], 'NONE'); - assert.equal(res.headers['cache-control'], expected_cache_control); + assert.ok(!res.hasOwnProperty('x-cache-channel')); + assert.equal(res.headers['cache-control'], expected_rw_cache_control); done(); }); }); @@ -511,8 +513,8 @@ test('TRUNCATE TABLE with GET and auth', function(done){ method: 'GET' },{}, function(res) { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - assert.equal(res.headers['x-cache-channel'], 'NONE'); - assert.equal(res.headers['cache-control'], expected_cache_control); + assert.ok(!res.hasOwnProperty('x-cache-channel')); + assert.equal(res.headers['cache-control'], expected_rw_cache_control); var pbody = JSON.parse(res.body); assert.equal(pbody.rows.length, 0); assert.response(app, { @@ -546,8 +548,8 @@ test('DROP TABLE with GET and auth', function(done){ assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); // Check cache headers // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/43 - assert.equal(res.headers['x-cache-channel'], 'NONE'); - assert.equal(res.headers['cache-control'], expected_cache_control); + assert.ok(!res.hasOwnProperty('x-cache-channel')); + assert.equal(res.headers['cache-control'], expected_rw_cache_control); done(); }); }); @@ -564,8 +566,8 @@ test('CREATE FUNCTION with GET and auth', function(done){ assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); // Check cache headers // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/43 - assert.equal(res.headers['x-cache-channel'], 'NONE'); - assert.equal(res.headers['cache-control'], expected_cache_control); + assert.ok(!res.hasOwnProperty('x-cache-channel')); + assert.equal(res.headers['cache-control'], expected_rw_cache_control); done(); }); }); @@ -582,8 +584,8 @@ test('DROP FUNCTION with GET and auth', function(done){ assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); // Check cache headers // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/43 - assert.equal(res.headers['x-cache-channel'], 'NONE'); - assert.equal(res.headers['cache-control'], expected_cache_control); + assert.ok(!res.hasOwnProperty('x-cache-channel')); + assert.equal(res.headers['cache-control'], expected_rw_cache_control); done(); }); });