node package manager
Don’t reinvent the wheel. Reuse code within your team. Create a free org »

popsicle-cache

Popsicle Cache

NPM version NPM downloads Build status Test coverage

Cache HTTP responses using popsicle.

Installation

npm install popsicle-cache --save

Usage

import { request } from 'popsicle'
import { plugin, cacheables, ttls } from 'popsicle-cache'
 
const cache = plugin({ engine: require('catbox-fs'), ttl: ttls.forever() })
 
popsicle('http://example.com')
  .use(cache.handle)
  .then(function (res) {
    console.log(res) //=> If still fresh, the cached response, otherwise it makes a new request. 
  })

Use popsicleCache.plugin(options) to initialize the cache middleware. It returns an object with three methods:

  • handle - Regular Popsicle middleware for handling the cache.
  • forceUpdate - Force a refresh of the cache on every request (does not read from cache, only sets it).
  • stop - Stop the underlying catbox engine.

Options

Popsicle Cache does not include any external caching strategy by default. Instead, it is compatible with catbox strategies.

engine (Object | Function)

An engine instance from catbox.

cacheable (Function, Default = cacheables.standard())

(req: Request, res: Response) => boolean

A function that determines whether a request/response should be cacheable.

Built-in cacheable implementations:

  • cacheables.standard() - Caches on res.status === 200 && req.method === 'GET' && !res.get('Cache-Control').contains('no-cache') only.
  • cacheables.always() - Always caches the response (return true).

ttl (Function, Default = ttls.standard(0, 1000 * 60 * 60 * 24 * 365))

(req: Request, res: Response) => number

A function that determines the TTL of the cached response.

Built-in TTL implementations:

  • ttls.standard(minTtl, maxTtl) - Calculates the freshness from the Cache-Control, Expires and/or Last-Modified headers. Returns minTtl + Math.min(maxTtl, freshness).
  • ttls.forever() - Caches forever (return Infinity).

serializer (Object, Default = serializers.standard())

interface Serializer <T> {
  name: string
  parse (value: string): T
  stringify (value: T, cache: (err: Error | null, value?: string | null) => void): T
}

An object that represents a serializer instance. Must have a name and implement parse and stringify methods. Some serializations are asynchronous in nature, or require the response body to be augmented, so a callback must be used to cache the actual value. Pass null or undefined as the cache value to skip the cache (E.g. cache() or cache(null, null)).

Built-in serializer implementations:

  • serializers.standard() - Simple implementation using JSON.parse and JSON.stringify.
  • stream(maxBufferLength?: number) - Buffers the response body from a stream, skipping the cache if the buffer exceeds maxBufferLength (defaults to 1mb)

handler (Function, Default = handlers.standard())

class CachedResponse extends popsicle.Response {
  ttl: number
  stored: number
  response: Response
  varyHeaders: Array<[string, string]>
}
 
(req: Request, cache: CachedResponse, next: () => Promise<Response>): Response | CachedResponse | Promise<Response | CachedResponse>

The request handler that decides whether to use the existing cache, regular response or a combination of both (E.g. by setting If-None-Match or If-Modified-Since).

Built-in handler implmentations:

  • handlers.standard() - Based on freshness, it will decide whether to use the cache directly or validate the cache by sending the request with If-None-Match or If-Modified-Since. If it responds with 304 (not modified), it will use the cached response body and headers.
  • handlers.always() - Always return the cached resource, even if expired or stale (return cache.response).

catchCacheError (Function, Default = undefined)

(err: Error) => void

Handler for catching cache errors. Useful for debugging errors with setting the cache engine or serializer errors which would otherwise be swallowed.

staleFallback (Boolean, Default = true)

When the network is down or the server responds with 5xx, we always default to the cached entry (instead of passing the error onward).

getId (Function, Default = getIds.standard())

The ID for the cache entry. The default is ${serializer.name}~${req.method}~${req.url}.

waitForCache (Boolean, Default = false)

Usually persisting to cache occurs in parallel with the response. This overrides that behaviour by waiting for the cache to finish before responding.

segment (String, Default = 'popsicle-cache')

The catbox segment name.

License

MIT license