From c7641381cdb8e2ca58b30f0db99e647a8f07f0a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kornel=20Lesin=CC=81ski?= Date: Tue, 21 Mar 2017 19:52:41 +0000 Subject: [PATCH] Change API to just return headers --- README.md | 10 ++++++++-- index.js | 15 +++++++-------- test/revalidatetest.js | 26 +++++++++++++------------- 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 2fb1ef7..795732b 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,11 @@ If it returns `false`, then the response may not be matching at all (e.g. it's f ### `responseHeaders()` -Returns updated, filtered set of response headers. Proxies MUST always remove hop-by-hop headers (such as `TE` and `Connection`) and update response age to avoid doubling cache time. +Returns updated, filtered set of response headers to return to clients receiving the cached response. This function is necessary, because proxies MUST always remove hop-by-hop headers (such as `TE` and `Connection`) and update response `Age` to avoid doubling cache time. + +### `revalidationHeaders()` + +Returns updated, filtered set of request headers to send to the origin server to check if the cached response can be reused. With this set of headers, the origin server may return status 304 indicating the response is still fresh. ### `timeToLive()` @@ -109,7 +113,9 @@ Chances are you'll want to store the `CachePolicy` object along with the cached * Default cacheability of statuses and methods. * Requests for stale data. * Filtering of hop-by-hop headers. +* Basic revalidation request ## Unimplemented -* There's no API for revalidation yet. +* Revalidation of multiple representations +* Updating of response after revalidation diff --git a/index.js b/index.js index 99d116c..669eabe 100644 --- a/index.js +++ b/index.js @@ -348,29 +348,28 @@ module.exports = class CachePolicy { }; } - validationRequest(incoming_req) { + revalidationHeaders(incoming_req) { this._assertRequestHasHeaders(incoming_req); if (!this._resHeaders.etag && !this._resHeaders['last-modified']) { - return incoming_req; // no validators available + return incoming_req.headers; // no validators available } // revalidation allowed via HEAD if (!this._requestMatches(incoming_req, true)) { - return incoming_req; // not for the same resource + return incoming_req.headers; // not for the same resource } - const upstream_req = Object.assign({}, incoming_req); - upstream_req.headers = Object.assign({}, incoming_req.headers); + const headers = Object.assign({}, incoming_req.headers); /* MUST send that entity-tag in any cache validation request (using If-Match or If-None-Match) if an entity-tag has been provided by the origin server. */ if (this._resHeaders.etag) { - upstream_req.headers['if-none-match'] = this._resHeaders.etag; + headers['if-none-match'] = this._resHeaders.etag; } /* SHOULD send the Last-Modified value in non-subrange cache validation requests (using If-Modified-Since) if only a Last-Modified value has been provided by the origin server. Note: This implementation does not understand partial responses (206) */ if (this._resHeaders['last-modified'] && this.storable()) { - upstream_req.headers['if-modified-since'] = this._resHeaders['last-modified']; + headers['if-modified-since'] = this._resHeaders['last-modified']; } - return upstream_req; + return headers; } }; diff --git a/test/revalidatetest.js b/test/revalidatetest.js index fb1024f..6f5d531 100644 --- a/test/revalidatetest.js +++ b/test/revalidatetest.js @@ -21,42 +21,42 @@ const alwaysVariableResponse = {headers:Object.assign({'vary':'*'},cacheableResp describe('Can be revalidated?', function() { it('ok if method changes to HEAD', function(){ const cache = new CachePolicy(simpleRequest,etaggedResponse); - const vReq = cache.validationRequest(simpleRequestBut({method:'HEAD'})); - assert.equal(vReq.headers['if-none-match'], '"123456789"'); + const headers = cache.revalidationHeaders(simpleRequestBut({method:'HEAD'})); + assert.equal(headers['if-none-match'], '"123456789"'); }); it('not if method mismatch (other than HEAD)',function(){ const cache = new CachePolicy(simpleRequest,etaggedResponse); const incomingRequest = simpleRequestBut({method:'POST'}); // Returns the same object unmodified, which means no custom validation - assert.strictEqual(incomingRequest, cache.validationRequest(incomingRequest)); + assert.strictEqual(incomingRequest.headers, cache.revalidationHeaders(incomingRequest)); }); it('not if url mismatch',function(){ const cache = new CachePolicy(simpleRequest,etaggedResponse); const incomingRequest = simpleRequestBut({url:'/yomomma'}); - assert.strictEqual(incomingRequest, cache.validationRequest(incomingRequest)); + assert.strictEqual(incomingRequest.headers, cache.revalidationHeaders(incomingRequest)); }); it('not if host mismatch',function(){ const cache = new CachePolicy(simpleRequest,etaggedResponse); const incomingRequest = simpleRequestBut({headers:{host:'www.w4c.org'}}); - assert.strictEqual(incomingRequest, cache.validationRequest(incomingRequest)); + assert.strictEqual(incomingRequest.headers, cache.revalidationHeaders(incomingRequest)); }); it('not if vary fields prevent',function(){ const cache = new CachePolicy(simpleRequest,alwaysVariableResponse); - assert.strictEqual(simpleRequest, cache.validationRequest(simpleRequest)); + assert.strictEqual(simpleRequest.headers, cache.revalidationHeaders(simpleRequest)); }); it('when entity tag validator is present', function() { const cache = new CachePolicy(simpleRequest, etaggedResponse); - const vReq = cache.validationRequest(simpleRequest); - assert.equal(vReq.headers['if-none-match'], '"123456789"'); + const headers = cache.revalidationHeaders(simpleRequest); + assert.equal(headers['if-none-match'], '"123456789"'); }); it('when last-modified validator is present', function() { const cache = new CachePolicy(simpleRequest, lastModifiedResponse); - const vReq = cache.validationRequest(simpleRequest); - assert.equal(vReq.headers['if-modified-since'], 'Tue, 15 Nov 1994 12:45:26 GMT'); + const headers = cache.revalidationHeaders(simpleRequest); + assert.equal(headers['if-modified-since'], 'Tue, 15 Nov 1994 12:45:26 GMT'); }); it('not without validators', function() { const cache = new CachePolicy(simpleRequest, cacheableResponse); - assert.strictEqual(simpleRequest, cache.validationRequest(simpleRequest)); + assert.strictEqual(simpleRequest.headers, cache.revalidationHeaders(simpleRequest)); }) }); @@ -65,13 +65,13 @@ describe('Validation request', function(){ it('must contain any etag', function(){ const cache = new CachePolicy(simpleRequest,multiValidatorResponse); const expected = multiValidatorResponse.headers.etag; - const actual = cache.validationRequest(simpleRequest).headers['if-none-match']; + const actual = cache.revalidationHeaders(simpleRequest)['if-none-match']; assert.equal(actual,expected); }); it('should send the Last-Modified value',function(){ const cache = new CachePolicy(simpleRequest,multiValidatorResponse); const expected = multiValidatorResponse.headers['last-modified']; - const actual = cache.validationRequest(simpleRequest).headers['if-modified-since']; + const actual = cache.revalidationHeaders(simpleRequest)['if-modified-since']; assert.equal(actual,expected); });