Comparing version 7.0.0 to 8.0.0
{ | ||
"name": "be-hippo", | ||
"version": "7.0.0", | ||
"version": "8.0.0", | ||
"description": "A PropositionH hypermedia consumer", | ||
@@ -10,2 +10,3 @@ "main": "./index.js", | ||
"spec": "./node_modules/karma/bin/karma start --singleRun", | ||
"test:dev": "./node_modules/karma/bin/karma start", | ||
"lint": "eslint ." | ||
@@ -31,7 +32,8 @@ }, | ||
"karma": "^1.1.2", | ||
"karma-chrome-launcher": "^0.1.4", | ||
"karma-coverage": "^0.2.5", | ||
"karma-chrome-launcher": "^1.0.1", | ||
"karma-coverage": "^1.1.1", | ||
"karma-jasmine": "^1.0.2", | ||
"karma-mocha-reporter": "^2.1.0", | ||
"karma-notify-reporter": "^1.0.1", | ||
"karma-phantomjs-launcher": "^1.0.1", | ||
"karma-sinon": "^1.0.5", | ||
@@ -38,0 +40,0 @@ "karma-webpack": "^1.7.0", |
@@ -5,3 +5,33 @@ import UriTemplate from './uritemplate'; | ||
const NO_CACHE_REGEX = /\b(?:no-cache|no-store)\b/; | ||
/** | ||
* @param {Headers} requestHeaders | ||
* @param {Headers} responseHeaders | ||
*/ | ||
function muxCacheHeaders(requestHeaders, responseHeaders) { | ||
// Using headers from: https://github.com/jshttp/fresh/blob/master/index.js | ||
if (responseHeaders.has('Last-Modified')) { | ||
requestHeaders.set('If-Modified-Since', responseHeaders.get('Last-Modified')); | ||
} | ||
if (responseHeaders.has('Etag')) { | ||
requestHeaders.set('If-None-Match', responseHeaders.get('Etag')); | ||
} | ||
} | ||
/** | ||
* @param {Response} response | ||
* @return {Boolean} | ||
*/ | ||
function isCacheable(response) { | ||
if (!response.ok) { | ||
return false; | ||
} | ||
if (response.headers.has('Cache-Control') && NO_CACHE_REGEX.test(response.headers.get('Cache-Control'))) { | ||
return false; | ||
} | ||
return response.headers.has('Last-Modified') || response.headers.has('Etag'); | ||
} | ||
/** | ||
* Resource | ||
@@ -16,2 +46,3 @@ * - descriptor: descripiton of the endpoint as given by the server | ||
this._parseDescriptor(descriptor); | ||
this._requestCache = new Map(); | ||
} | ||
@@ -46,3 +77,33 @@ | ||
get(params, options) { return this._issueRequest('get', params, null, options); } | ||
_constructRequestOptions(method, params, body, options = {}) { | ||
const selfConn = this.getConnection({ name: 'self', data: params || {} }); | ||
const requestOptions = merge({}, this._requestOptions, options, { method }); | ||
requestOptions.headers = new Headers(requestOptions.headers); | ||
if (body && !requestOptions.body) { | ||
requestOptions.body = body; | ||
} | ||
return { | ||
url: selfConn, | ||
requestOptions | ||
}; | ||
} | ||
get(params, options = {}) { | ||
const { url, requestOptions } = this._constructRequestOptions('get', params, null, options); | ||
// set cache headers | ||
if (!NO_CACHE_REGEX.test(requestOptions.cache || '') && this._requestCache.has(url)) { | ||
muxCacheHeaders(requestOptions.headers, this._requestCache.get(url).headers); | ||
} | ||
return xhr(url, requestOptions) | ||
.then((res) => { | ||
if (res.status === 304 && this._requestCache.has(url)) { | ||
return this._requestCache.get(url).clone(); | ||
} | ||
if (isCacheable(res)) { | ||
this._requestCache.set(url, res.clone()); | ||
} | ||
return res; | ||
}); | ||
} | ||
head(params, options) { return this._issueRequest('head', params, null, options); } | ||
@@ -56,9 +117,4 @@ | ||
_issueRequest(method, params, body, options = {}) { | ||
var selfConn = this.getConnection({ name: 'self', data: params || {} }); | ||
var requestOptions = merge({}, this._requestOptions, options, { method }); | ||
if (body && !requestOptions.body) { | ||
requestOptions.body = body; | ||
} | ||
return xhr(selfConn, requestOptions); | ||
const { url, requestOptions } = this._constructRequestOptions(method, params, body, options); | ||
return xhr(url, requestOptions); | ||
} | ||
@@ -85,2 +141,6 @@ | ||
} | ||
clearCache() { | ||
this._requestCache.clear(); | ||
} | ||
} |
@@ -228,2 +228,145 @@ import Resource from 'src/resource'; | ||
}); | ||
describe('when server responds with cache headers', function() { | ||
it('caches subsequent cache-able requests with last-modified', function(done) { | ||
var resource = new Resource(descriptor); | ||
let counter = 0; | ||
server.respondWith('GET', '/v1/foo?bar=10', function(req) { | ||
counter++; | ||
if (!req.requestHeaders['if-modified-since']) { | ||
expect(counter).toEqual(1); | ||
req.respond(200, { | ||
'Content-Type': 'application/json', | ||
'Last-Modified': 'Tue, 09 Aug 2016 14:23:49 GMT' | ||
}, JSON.stringify(result)); | ||
return; | ||
} | ||
expect(counter).toBeGreaterThan(1); | ||
expect(req.requestHeaders['if-modified-since']).toEqual('Tue, 09 Aug 2016 14:23:49 GMT'); | ||
req.respond(304, {}, ''); | ||
}); | ||
resource.get({ bar: 10 }) | ||
.then((res) => res.json()) | ||
.then((data) => { | ||
expect(data.hello).toEqual('world'); | ||
return resource.get({ bar: 10 }); | ||
}) | ||
.then((res) => res.json()) | ||
.then((data) => { | ||
expect(data.hello).toEqual('world'); | ||
}) | ||
.then(done, done.fail); | ||
}); | ||
it('caches subsequent cache-able requests with etag', function(done) { | ||
var resource = new Resource(descriptor); | ||
let counter = 0; | ||
server.respondWith('GET', '/v1/foo?bar=10', function(req) { | ||
counter++; | ||
if (!req.requestHeaders['if-none-match']) { | ||
expect(counter).toEqual(1); | ||
req.respond(200, { | ||
'Content-Type': 'application/json', | ||
Etag: 'foobar' | ||
}, JSON.stringify(result)); | ||
return; | ||
} | ||
expect(counter).toBeGreaterThan(1); | ||
expect(req.requestHeaders['if-none-match']).toEqual('foobar'); | ||
req.respond(304, {}, ''); | ||
}); | ||
resource.get({ bar: 10 }) | ||
.then((res) => res.json()) | ||
.then((data) => { | ||
expect(data.hello).toEqual('world'); | ||
return resource.get({ bar: 10 }); | ||
}) | ||
.then((res) => res.json()) | ||
.then((data) => { | ||
expect(data.hello).toEqual('world'); | ||
}) | ||
.then(done, done.fail); | ||
}); | ||
}); | ||
describe('when server responds with cache-control headers', function() { | ||
it('caches subsequent cache-able requests with last-modified', function(done) { | ||
var resource = new Resource(descriptor); | ||
let counter = 0; | ||
server.respondWith('GET', '/v1/foo?bar=10', function(req) { | ||
counter++; | ||
expect(req.requestHeaders['if-modified-since']).toBeUndefined(); | ||
if (!req.requestHeaders['if-modified-since']) { | ||
req.respond(200, { | ||
'Content-Type': 'application/json', | ||
'Last-Modified': 'Tue, 09 Aug 2016 14:23:49 GMT', | ||
'Cache-Control': 'no-cache' | ||
}, JSON.stringify({ counter })); | ||
return; | ||
} | ||
req.respond(304, {}, ''); | ||
}); | ||
resource.get({ bar: 10 }) | ||
.then((res) => res.json()) | ||
.then((data) => { | ||
expect(data.counter).toEqual(1); | ||
return resource.get({ bar: 10 }); | ||
}) | ||
.then((res) => res.json()) | ||
.then((data) => { | ||
expect(data.counter).toEqual(2); | ||
return resource.get({ bar: 10 }); | ||
}) | ||
.then((res) => res.json()) | ||
.then((data) => { | ||
expect(data.counter).toEqual(3); | ||
}) | ||
.then(done, done.fail); | ||
}); | ||
}); | ||
describe('when client requests with no-cache', function() { | ||
it('caches subsequent cache-able requests with last-modified', function(done) { | ||
var resource = new Resource(descriptor); | ||
let counter = 0; | ||
server.respondWith('GET', '/v1/foo?bar=10', function(req) { | ||
counter++; | ||
expect(req.requestHeaders['if-modified-since']).toBeUndefined(); | ||
if (!req.requestHeaders['if-modified-since']) { | ||
req.respond(200, { | ||
'Content-Type': 'application/json', | ||
'Last-Modified': 'Tue, 09 Aug 2016 14:23:49 GMT' | ||
}, JSON.stringify({ counter })); | ||
return; | ||
} | ||
req.respond(304, {}, ''); | ||
}); | ||
resource.get({ bar: 10 }, { cache: 'no-cache' }) | ||
.then((res) => res.json()) | ||
.then((data) => { | ||
expect(data.counter).toEqual(1); | ||
return resource.get({ bar: 10 }, { cache: 'no-cache' }); | ||
}) | ||
.then((res) => res.json()) | ||
.then((data) => { | ||
expect(data.counter).toEqual(2); | ||
return resource.get({ bar: 10 }, { cache: 'no-cache' }); | ||
}) | ||
.then((res) => res.json()) | ||
.then((data) => { | ||
expect(data.counter).toEqual(3); | ||
}) | ||
.then(done, done.fail); | ||
}); | ||
}); | ||
}); | ||
@@ -230,0 +373,0 @@ |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
83143
2307
0
24