Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

http-cache-semantics

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

http-cache-semantics - npm Package Compare versions

Comparing version 1.0.0 to 2.0.0

test/requesttest.js

93

index.js
'use strict';
// rfc7231 6.1
const statusCodeCacheableByDefault = [200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501];
// This implementation does not understand partial responses (206)
const understoodStatuses = [200, 204, 301, 302, 303, 404, 410, 501];
function parseCacheControl(header) {

@@ -24,4 +30,7 @@ const cc = {};

if (!res || !res.headers) {
throw Error("headers missing");
throw Error("Response headers missing");
}
if (!req || !req.headers) {
throw Error("Request headers missing");
}

@@ -31,3 +40,5 @@ this._responseTime = this.now();

this._res = res;
this._cc = parseCacheControl(res.headers['cache-control']);
this._rescc = parseCacheControl(res.headers['cache-control']);
this._req = req;
this._reqcc = parseCacheControl(req.headers['cache-control']);

@@ -37,3 +48,3 @@ // When the Cache-Control header field is not present in a request, caches MUST consider the no-cache request pragma-directive

if (!res.headers['cache-control'] && /no-cache/.test(res.headers.pragma)) {
this._cc['no-cache'] = true;
this._rescc['no-cache'] = true;
}

@@ -47,2 +58,59 @@ }

storable() {
const status = (this._res.status === undefined) ? 200 : this._res.status;
// The "no-store" request directive indicates that a cache MUST NOT store any part of either this request or any response to it.
return !this._reqcc['no-store'] &&
// A cache MUST NOT store a response to any request, unless:
// The request method is understood by the cache and defined as being cacheable, and
(!this._req.method || 'GET' === this._req.method || 'HEAD' === this._req.method || ('POST' === this._req.method && this._hasExplicitExpiration())) &&
// the response status code is understood by the cache, and
understoodStatuses.includes(status) &&
// the "no-store" cache directive does not appear in request or response header fields, and
!this._rescc['no-store'] &&
// the "private" response directive does not appear in the response, if the cache is shared, and
(!this._isShared || !this._rescc.private) &&
// the Authorization header field does not appear in the request, if the cache is shared,
(!this._isShared || !this._req.headers['authorization'] || this._allowsStoringAuthenticated()) &&
// the response either:
(
// contains an Expires header field, or
this._res.headers.expires ||
// contains a max-age response directive, or
// contains a s-maxage response directive and the cache is shared, or
// contains a public response directive.
this._rescc.public || this._rescc['max-age'] || this._rescc['s-maxage'] ||
// has a status code that is defined as cacheable by default
statusCodeCacheableByDefault.includes(status)
);
},
_hasExplicitExpiration() {
// 4.2.1 Calculating Freshness Lifetime
return (this._isShared && this._rescc['s-maxage']) ||
this._rescc['max-age'] ||
this._res.headers.expires;
},
_allowsStoringAuthenticated() {
// following Cache-Control response directives (Section 5.2.2) have such an effect: must-revalidate, public, and s-maxage.
return this._rescc['must-revalidate'] || this._rescc['public'] || this._rescc['s-maxage'];
},
_varyKeyForRequest(req) {
if (!this._res.headers.vary) return '';
let key = '';
const fields = this._res.headers.vary.toLowerCase().split(/\s*,\s*/);
fields.sort();
for(const name of fields) {
key += `${name}:${req.headers[name] || '÷'}\n`;
}
return key;
},
cacheKey() {
return `${this._req.method || 'GET'} ${this._req.url || ''} ${this._varyKeyForRequest(this._req)}`;
},
/**

@@ -79,3 +147,3 @@ * Value of the Date response header or current time if Date was demed invalid

maxAge() {
if (this._cc['no-cache'] || this._cc['no-store']) {
if (!this.storable() || this._rescc['no-cache']) {
return 0;

@@ -86,8 +154,7 @@ }

// so this implementation requires explicit opt-in via public header
if (this._isShared && (this._cc['private'] || (this._res.headers['set-cookie'] && !this._cc['public']))) {
if (this._isShared && (this._res.headers['set-cookie'] && !this._rescc['public'])) {
return 0;
}
// TODO: vary is not supported yet
if (this._res.headers['vary']) {
if (this._res.headers.vary === '*') {
return 0;

@@ -98,4 +165,4 @@ }

// if a response includes the s-maxage directive, a shared cache recipient MUST ignore the Expires field.
if (this._cc['s-maxage']) {
return parseInt(this._cc['s-maxage'], 10);
if (this._rescc['s-maxage']) {
return parseInt(this._rescc['s-maxage'], 10);
}

@@ -105,4 +172,4 @@ }

// If a response includes a Cache-Control field with the max-age directive, a recipient MUST ignore the Expires field.
if (this._cc['max-age']) {
return parseInt(this._cc['max-age'], 10);
if (this._rescc['max-age']) {
return parseInt(this._rescc['max-age'], 10);
}

@@ -129,4 +196,4 @@

isFresh() {
return this.maxAge() > this.age();
stale() {
return this.maxAge() <= this.age();
},

@@ -133,0 +200,0 @@ };

2

package.json
{
"name": "http-cache-semantics",
"version": "1.0.0",
"version": "2.0.0",
"description": "Parses Cache-Control headers and friends",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -15,3 +15,3 @@ # HTTP cache semantics

// Current state
const currentState = cache.isFresh();
const outOfDate = cache.stale();
```

@@ -43,2 +43,14 @@

### `stale()`
Returns `true` if the response is stale (i.e. not fresh).
It generally means the response can't be used any more without revalidation with the server. However, there are exceptions, e.g. client can explicitly allow stale responses. A fresh response still may not be used if other conditions—such as `Vary`—are not satisfied.
### `cacheKey()`
Returns a string that is a combination of method, URL, and headers selected with `Vary`.
Note that `Vary: *` never matches any request, so matching of cache keys alone is not sufficient to satisfy a request.
## Implemented

@@ -50,7 +62,7 @@

* `Age` response header
* Default cacheability of statuses and methods
* Basic support for `Vary`
## Unimplemented
* Request properties are not evaluated
* `Vary` support is as lame and incomplete as in web browsers
* No support for revalidation and stale responses
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc