http-cache-semantics
Advanced tools
Comparing version 3.5.0 to 3.5.1
46
index.js
@@ -192,11 +192,11 @@ 'use strict'; | ||
responseHeaders() { | ||
_copyWithoutHopByHopHeaders(inHeaders) { | ||
const headers = {}; | ||
for(const name in this._resHeaders) { | ||
for(const name in inHeaders) { | ||
if (hopByHopHeaders[name]) continue; | ||
headers[name] = this._resHeaders[name]; | ||
headers[name] = inHeaders[name]; | ||
} | ||
// 9.1. Connection | ||
if (this._resHeaders.connection) { | ||
const tokens = this._resHeaders.connection.trim().split(/\s*,\s*/); | ||
if (inHeaders.connection) { | ||
const tokens = inHeaders.connection.trim().split(/\s*,\s*/); | ||
for(const name of tokens) { | ||
@@ -216,2 +216,7 @@ delete headers[name]; | ||
} | ||
return headers; | ||
} | ||
responseHeaders() { | ||
const headers = this._copyWithoutHopByHopHeaders(this._resHeaders); | ||
headers.age = `${Math.round(this.age())}`; | ||
@@ -353,21 +358,28 @@ return headers; | ||
revalidationHeaders(incoming_req) { | ||
this._assertRequestHasHeaders(incoming_req); | ||
if (!this._resHeaders.etag && !this._resHeaders['last-modified']) { | ||
return incoming_req.headers; // no validators available | ||
/** | ||
* Headers for sending to the origin server to revalidate stale response. | ||
* Allows server to return 304 to allow reuse of the previous response. | ||
* | ||
* Hop by hop headers are always stripped. | ||
* Revalidation headers may be added or removed, depending on request. | ||
*/ | ||
revalidationHeaders(incomingReq) { | ||
this._assertRequestHasHeaders(incomingReq); | ||
const headers = this._copyWithoutHopByHopHeaders(incomingReq.headers); | ||
if (!this._requestMatches(incomingReq, true) || !this.storable()) { // revalidation allowed via HEAD | ||
// not for the same resource, or wasn't allowed to be cached anyway | ||
delete headers['if-none-match']; | ||
delete headers['if-modified-since']; | ||
return headers; | ||
} | ||
// revalidation allowed via HEAD | ||
if (!this._requestMatches(incoming_req, true)) { | ||
return incoming_req.headers; // not for the same resource | ||
} | ||
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) { | ||
headers['if-none-match'] = this._resHeaders.etag; | ||
headers['if-none-match'] = headers['if-none-match'] ? `${headers['if-none-match']}, ${this._resHeaders.etag}` : 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()) { | ||
if (this._resHeaders['last-modified'] && !headers['if-modified-since']) { | ||
headers['if-modified-since'] = this._resHeaders['last-modified']; | ||
@@ -374,0 +386,0 @@ } |
{ | ||
"name": "http-cache-semantics", | ||
"version": "3.5.0", | ||
"version": "3.5.1", | ||
"description": "Parses Cache-Control and other headers. Helps building correct HTTP caches and proxies", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -8,3 +8,7 @@ 'use strict'; | ||
method:'GET', | ||
headers:{host:'www.w3c.org'}, | ||
headers:{ | ||
host:'www.w3c.org', | ||
connection: 'close', | ||
'x-custom': 'yes', | ||
}, | ||
url:'/Protocols/rfc2616/rfc2616-sec14.html', | ||
@@ -22,41 +26,70 @@ }; | ||
function assertHeadersPassed(headers) { | ||
assert.strictEqual(headers.connection, undefined); | ||
assert.strictEqual(headers['x-custom'], 'yes'); | ||
} | ||
function assertNoValidators(headers) { | ||
assert.strictEqual(headers['if-none-match'], undefined); | ||
assert.strictEqual(headers['if-modified-since'], undefined); | ||
} | ||
describe('Can be revalidated?', function() { | ||
it('ok if method changes to HEAD', function(){ | ||
const cache = new CachePolicy(simpleRequest,etaggedResponse); | ||
const headers = cache.revalidationHeaders(simpleRequestBut({method:'HEAD'})); | ||
assert.equal(headers['if-none-match'], '"123456789"'); | ||
const cache = new CachePolicy(simpleRequest,etaggedResponse); | ||
const headers = cache.revalidationHeaders(simpleRequestBut({method:'HEAD'})); | ||
assertHeadersPassed(headers); | ||
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.headers, cache.revalidationHeaders(incomingRequest)); | ||
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 | ||
const headers = cache.revalidationHeaders(incomingRequest); | ||
assertHeadersPassed(headers); | ||
assertNoValidators(headers); | ||
}); | ||
it('not if url mismatch',function(){ | ||
const cache = new CachePolicy(simpleRequest,etaggedResponse); | ||
const incomingRequest = simpleRequestBut({url:'/yomomma'}); | ||
assert.strictEqual(incomingRequest.headers, cache.revalidationHeaders(incomingRequest)); | ||
it('not if url mismatch', function(){ | ||
const cache = new CachePolicy(simpleRequest,etaggedResponse); | ||
const incomingRequest = simpleRequestBut({url:'/yomomma'}); | ||
const headers = cache.revalidationHeaders(incomingRequest); | ||
assertHeadersPassed(headers); | ||
assertNoValidators(headers); | ||
}); | ||
it('not if host mismatch',function(){ | ||
it('not if host mismatch', function(){ | ||
const cache = new CachePolicy(simpleRequest,etaggedResponse); | ||
const incomingRequest = simpleRequestBut({headers:{host:'www.w4c.org'}}); | ||
assert.strictEqual(incomingRequest.headers, cache.revalidationHeaders(incomingRequest)); | ||
const headers = cache.revalidationHeaders(incomingRequest); | ||
assertNoValidators(headers); | ||
assert.strictEqual(headers['x-custom'], undefined); | ||
}); | ||
it('not if vary fields prevent',function(){ | ||
const cache = new CachePolicy(simpleRequest,alwaysVariableResponse); | ||
assert.strictEqual(simpleRequest.headers, cache.revalidationHeaders(simpleRequest)); | ||
it('not if vary fields prevent', function(){ | ||
const cache = new CachePolicy(simpleRequest,alwaysVariableResponse); | ||
const headers = cache.revalidationHeaders(simpleRequest); | ||
assertHeadersPassed(headers); | ||
assertNoValidators(headers); | ||
}); | ||
it('when entity tag validator is present', function() { | ||
const cache = new CachePolicy(simpleRequest, etaggedResponse); | ||
const headers = cache.revalidationHeaders(simpleRequest); | ||
assertHeadersPassed(headers); | ||
assert.equal(headers['if-none-match'], '"123456789"'); | ||
}); | ||
it('when last-modified validator is present', function() { | ||
const cache = new CachePolicy(simpleRequest, lastModifiedResponse); | ||
const headers = cache.revalidationHeaders(simpleRequest); | ||
assert.equal(headers['if-modified-since'], 'Tue, 15 Nov 1994 12:45:26 GMT'); | ||
const cache = new CachePolicy(simpleRequest, lastModifiedResponse); | ||
const headers = cache.revalidationHeaders(simpleRequest); | ||
assertHeadersPassed(headers); | ||
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.headers, cache.revalidationHeaders(simpleRequest)); | ||
const headers = cache.revalidationHeaders(simpleRequest); | ||
assertHeadersPassed(headers); | ||
assertNoValidators(headers); | ||
}) | ||
@@ -67,2 +100,3 @@ | ||
describe('Validation request', function(){ | ||
it('must contain any etag', function(){ | ||
@@ -74,3 +108,4 @@ const cache = new CachePolicy(simpleRequest,multiValidatorResponse); | ||
}); | ||
it('should send the Last-Modified value',function(){ | ||
it('should send the Last-Modified value', function(){ | ||
const cache = new CachePolicy(simpleRequest,multiValidatorResponse); | ||
@@ -77,0 +112,0 @@ const expected = multiValidatorResponse.headers['last-modified']; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
56021
1133