Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/bbc/http-transport-cache
A HTTP spec compliant caching layer for http-transport.
https://github.com/bbc/http-transport-cache
ignorearchive
Last synced: 3 months ago
JSON representation
A HTTP spec compliant caching layer for http-transport.
- Host: GitHub
- URL: https://github.com/bbc/http-transport-cache
- Owner: bbc
- License: other
- Created: 2017-08-24T08:25:34.000Z (over 7 years ago)
- Default Branch: main
- Last Pushed: 2024-10-18T07:45:55.000Z (3 months ago)
- Last Synced: 2024-11-02T19:33:52.600Z (3 months ago)
- Topics: ignorearchive
- Language: JavaScript
- Homepage:
- Size: 213 KB
- Stars: 3
- Watchers: 21
- Forks: 5
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Contributing: .github/CONTRIBUTING.md
- License: LICENSE
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
README
[![NPM downloads](https://img.shields.io/npm/dm/@bbc/http-transport-cache.svg?style=flat)](https://npmjs.org/package/@bbc/http-transport-cache)
![npm](https://img.shields.io/npm/v/@bbc/http-transport-cache.svg)
![license](https://img.shields.io/badge/license-MIT-blue.svg)
![github-issues](https://img.shields.io/github/issues/bbc/http-transport-cache.svg)
![stars](https://img.shields.io/github/stars/bbc/http-transport-cache.svg)
![forks](https://img.shields.io/github/forks/bbc/http-transport-cache.svg)# HTTP Transport Cache
A HTTP spec compliant caching layer for `http-transport`.
## Installation
```
npm install --save http-transport-cache
```## Usage
Configure response caching based on max-age:
```js
const cache = require('@bbc/http-transport-cache');
const Catbox = require('@hapi/catbox');
const HttpTransport = require('@bbc/http-transport');const catbox = new Catbox.Client(new Memory());
const url = 'http://example.com/';
const client = HttpTransport.createBuilder()
.use(cache.maxAge(catbox))
.createClient();const body = await client.get(url)
.asBody();console.log(body);
```Configure stale-if-error:
```js
const cache = require('@bbc/http-transport-cache');
const Catbox = require('catbox');
const HttpTransport = require('@bbc/http-transport');const catbox = new Catbox.Client(new Memory());
const url = 'http://example.com/';
const client = HttpTransport.createClient()
.use(cache.staleIfError(catbox))
.createClient();const body = await client.get(url)
.asBody();console.log(body);
```Listening to Events:
``` JS
const { events, maxAge } = require('@bbc/http-transport-cache');const stats = require('@ibl/stats');
const Catbox = require('catbox');
const HttpTransport = require('@bbc/http-transport');const catbox = new Catbox.Client(new Memory());
const url = 'http://example.com/';
const client = HttpTransport.createBuilder()
.use(cache.maxAge(catbox, {
name: `theservice`,
}))
.createClient();events.on(`cache.theservice.read_time`, (ctx) => {
stats.timing(`timingstat.read_time`, ctx.duration);
});
```## Features
|Feature|Description|
|----|-----------|
|Warnings|The cached response only contains the simplified `http-transport` request and response so as not to waste cache space.|
|Max Age|Responses are stored for the duration of the `max-age` directive and are used before any requests are made.|
|Stale If Error|In order to ensure a resilient service even during errors, http responses can include a `cache-control` directive called `stale-if-error` which means we can use a cached response for that period whilst the service is erroring. To do this a separate response blob is stored for the stale period and on error this response is used alongside the body which is stored for the higher of either `max-age` or `stale-if-error`.|
|No Store|If `no-store` directive is present in the response, it will not be stored / cached anywhere.|
|Private|If `private` directive is present in the response, it will not be stored by shared cache. The response will only be stored in a private cache intended for a single user.|### Events
- hit
- miss
- error
- timeout
- stale
- read_time
- write_time
- connection_error## Middleware Options
Both `maxage` and `staleIfError` accept an options object.
|Property|type|module|Description|
|----|----|----|-----------|
|`ignoreCacheErrors`|boolean|maxAge,staleIfError| `cache.maxAge` will return a cache miss when this property is `true`. Setting this property true for `cache.staleIfError` will rethrow the original error (not the cache lookup error). `ignoreCacheErrors` is `false` by default.|
|`timeout`|integer|maxAge|Timeouts a cache lookup after a specified number of ms. By default, no timeout is specified.|
|`connectionTimeout`|integer|maxAge,staleIfError|Timeouts the attempt to connect to a cache after a specified number of ms. By default, no timeout is specified.|
|`connectionCircuitBreakerOptions`|object|maxAge,staleIfError| When present an instance of [Levee](https://github.com/krakenjs/levee) will be created with these configuration options to use on connection to cache.|
|`includeCacheStatusInCtx`|boolean|maxAge,staleIfError| When present, a `cacheStatus` array - recording all cache events, will be set in `context` for use by other plugins. `includeCacheStatusInCtx` is `false` by default.|## Cache version
The cache verison is stored in the `config.json`, this is distinct from the library version in the `package.json`. The cache version is used in the cache key and is intended to reduce cache fragmentation in a scenario where multiple different versions of this library might be in use across a single estate.
The cache version **must** be incremented if a change is made to the data stored in the cache that would be incompatible with the existing version. Otherwise it should not be changed.
## Cache Key Structure
The cache uses `catbox` to provide a simple pluggable interface, this supports segmenting the cache as well as IDs, thus the following segments are used:* http-transport:{version}:response - Basic response from a call cached for the duration of the `max-age` value key on just the URL of the response.
* http-transport:{version}:staleResponse - Stale response from a called cached for the `stale-if-error` value keyed on just the URL of the response.Additionally, cache keys can be configured by passing a `varyOn` option. `varyOn` should contain an array of request header names which the cache should additionally vary on; for some use-cases, requests made to the same endpoint but with differing values for certain headers elicit different responses - and therefore cannot share the same cached response e.g.`accept-language`. By letting `http-transport-cache` know which headers to vary on, a unique cache key will be constructed which also contains said headers and their values.
Example:
We make a `GET` request to the following URL: `www.example.com/some-cacheable-path`.
We vary on `accept-language` and `accept`. These headers will exist in the request. We pass in `varyOn` (an array of request headers we vary on) together with other options to configure the plugin.
```js
const opts = {
timeout: 2000,
varyOn: [
'accept-language',
'accept'
]
};
```On the first request, the value of `accept-language` is `en` and `accept` is `application/json`. The resulting key will be:
* GET:www.example.com/some-cacheable-path:accept-language=en,accept=application/json
On the second request, the value of `accept-language` is `fr` and `accept` is `text/html`. The resulting key will be:
* GET:www.example.com/some-cacheable-path:accept-language=fr,accept=text/html
This way we avoid overwritting data in the store.
## Test
```
npm test
```To generate a test coverage report:
```
npm run coverage
```