Browse Source

Change API to just return headers

master
Kornel Lesiński 8 years ago
parent
commit
c7641381cd
  1. 10
      README.md
  2. 15
      index.js
  3. 26
      test/revalidatetest.js

10
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()` ### `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()` ### `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. * Default cacheability of statuses and methods.
* Requests for stale data. * Requests for stale data.
* Filtering of hop-by-hop headers. * Filtering of hop-by-hop headers.
* Basic revalidation request
## Unimplemented ## Unimplemented
* There's no API for revalidation yet. * Revalidation of multiple representations
* Updating of response after revalidation

15
index.js

@ -348,29 +348,28 @@ module.exports = class CachePolicy {
}; };
} }
validationRequest(incoming_req) { revalidationHeaders(incoming_req) {
this._assertRequestHasHeaders(incoming_req); this._assertRequestHasHeaders(incoming_req);
if (!this._resHeaders.etag && !this._resHeaders['last-modified']) { 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 // revalidation allowed via HEAD
if (!this._requestMatches(incoming_req, true)) { 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); const headers = Object.assign({}, incoming_req.headers);
upstream_req.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. */ /* 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) { 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. /* 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) */ Note: This implementation does not understand partial responses (206) */
if (this._resHeaders['last-modified'] && this.storable()) { 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;
} }
}; };

26
test/revalidatetest.js

@ -21,42 +21,42 @@ const alwaysVariableResponse = {headers:Object.assign({'vary':'*'},cacheableResp
describe('Can be revalidated?', function() { describe('Can be revalidated?', function() {
it('ok if method changes to HEAD', function(){ it('ok if method changes to HEAD', function(){
const cache = new CachePolicy(simpleRequest,etaggedResponse); const cache = new CachePolicy(simpleRequest,etaggedResponse);
const vReq = cache.validationRequest(simpleRequestBut({method:'HEAD'})); const headers = cache.revalidationHeaders(simpleRequestBut({method:'HEAD'}));
assert.equal(vReq.headers['if-none-match'], '"123456789"'); assert.equal(headers['if-none-match'], '"123456789"');
}); });
it('not if method mismatch (other than HEAD)',function(){ it('not if method mismatch (other than HEAD)',function(){
const cache = new CachePolicy(simpleRequest,etaggedResponse); const cache = new CachePolicy(simpleRequest,etaggedResponse);
const incomingRequest = simpleRequestBut({method:'POST'}); const incomingRequest = simpleRequestBut({method:'POST'});
// Returns the same object unmodified, which means no custom validation // 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(){ it('not if url mismatch',function(){
const cache = new CachePolicy(simpleRequest,etaggedResponse); const cache = new CachePolicy(simpleRequest,etaggedResponse);
const incomingRequest = simpleRequestBut({url:'/yomomma'}); const incomingRequest = simpleRequestBut({url:'/yomomma'});
assert.strictEqual(incomingRequest, cache.validationRequest(incomingRequest)); assert.strictEqual(incomingRequest.headers, cache.revalidationHeaders(incomingRequest));
}); });
it('not if host mismatch',function(){ it('not if host mismatch',function(){
const cache = new CachePolicy(simpleRequest,etaggedResponse); const cache = new CachePolicy(simpleRequest,etaggedResponse);
const incomingRequest = simpleRequestBut({headers:{host:'www.w4c.org'}}); 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(){ it('not if vary fields prevent',function(){
const cache = new CachePolicy(simpleRequest,alwaysVariableResponse); 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() { it('when entity tag validator is present', function() {
const cache = new CachePolicy(simpleRequest, etaggedResponse); const cache = new CachePolicy(simpleRequest, etaggedResponse);
const vReq = cache.validationRequest(simpleRequest); const headers = cache.revalidationHeaders(simpleRequest);
assert.equal(vReq.headers['if-none-match'], '"123456789"'); assert.equal(headers['if-none-match'], '"123456789"');
}); });
it('when last-modified validator is present', function() { it('when last-modified validator is present', function() {
const cache = new CachePolicy(simpleRequest, lastModifiedResponse); const cache = new CachePolicy(simpleRequest, lastModifiedResponse);
const vReq = cache.validationRequest(simpleRequest); const headers = cache.revalidationHeaders(simpleRequest);
assert.equal(vReq.headers['if-modified-since'], 'Tue, 15 Nov 1994 12:45:26 GMT'); assert.equal(headers['if-modified-since'], 'Tue, 15 Nov 1994 12:45:26 GMT');
}); });
it('not without validators', function() { it('not without validators', function() {
const cache = new CachePolicy(simpleRequest, cacheableResponse); 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(){ it('must contain any etag', function(){
const cache = new CachePolicy(simpleRequest,multiValidatorResponse); const cache = new CachePolicy(simpleRequest,multiValidatorResponse);
const expected = multiValidatorResponse.headers.etag; 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); assert.equal(actual,expected);
}); });
it('should send the Last-Modified value',function(){ it('should send the Last-Modified value',function(){
const cache = new CachePolicy(simpleRequest,multiValidatorResponse); const cache = new CachePolicy(simpleRequest,multiValidatorResponse);
const expected = multiValidatorResponse.headers['last-modified']; 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); assert.equal(actual,expected);
}); });

Loading…
Cancel
Save