npm package: @stream-connect/helper-http2-push-cache
Description: HTTP/2 auto-push library
Author: Google LLC
Latest version: 0.1.1

# HTTP/2 automatic server push

[![Greenkeeper badge](https://badges.greenkeeper.io/google/node-h2-auto-push.svg)](https://greenkeeper.io/)

**This is not an official Google product.**

[HTTP/2](https://tools.ietf.org/html/rfc7540) is a major revision of the HTTP
protocol. One of its differences from HTTP/1 is [*server
push*](https://tools.ietf.org/html/rfc7540#section-8.2), which allows a
server to pre-emptively send responses to a client in association with a
previous client-initiated request. This can be useful when the server knows
the client will need to have those responses available in order to fully
process the response to the original request.

It sounds simple and easy but is quite tricky for service developers to
manually figure out and configure what resources to push in association with
another resource. There are also many pitfalls the implementors must know
about. See [Rules of Thumb for HTTP/2
Push](https://docs.google.com/document/d/1K0NykTXBbbbTlv60t5MyJvXjqKGsCVNYHyLEXIxYMv0/edit?usp=sharing)
for the details.

This project is for automating server push and getting rid of the need for
manual configurations from service developers. It is meant as a helper
library for building middlewares for various [Node.js](https://nodejs.org)
web servers, such as [Express](http://expressjs.com/),
[fastify](https://www.fastify.io/), etc.

This library assumes that the middlewares built on top of it act as a static
file server. That is because static file serving is one of the most common
use cases for HTTP/2 server push.

See https://github.com/google/node-fastify-auto-push for an example. It is a
[fastify](https://www.fastify.io/) plugin for supporting auto-push.

**This package currently works only with Node >=9.4.0.**

## Interface

### `class AutoPush`

#### Constructor

```typescript
constructor(rootDir: string, cacheConfig?: AssetCacheConfig);
```

Constructs an `AutoPush` object.

*   `rootDir`: Top-level directory that contains the static files to be served.
*   `cacheConfig`: Configuration options for customizing the caching behavior.

#### `preprocessRequest()`

```typescript
preprocessRequest(
    reqPath: string,
    stream: http2.ServerHttp2Stream,
    cacheCookie?: string): Promise<PreprocessResult>;

interface PreprocessResult {
  newCacheCookie: string;
  pushFn: () => Promise<void>;
}
```

This method must be called for every request from the client. It determines
which other resources must be pushed, if any, in association with the current
request path. It also checks whether any resources to be pushed are already
cached in the browser side. It is done by storing and reading the related
information in a cookie value.

*   `reqPath`: The request path given from the client.
*   `stream`: The current `ServerHttp2Stream` object.
*   `cacheCookie`: The value of the cookie used for storing the information on
    which resources are cached in the browser. It is up to the middleware
    which cookie to use for this.

Returns a promise for the result (`PreprocessResult`). The middleware must
use the `newCacheCookie` value to store it in the browser cookie, and use
`pushFn` to push static resources that are associated with the current
request.

This method (and `recordRequestPath()` described below) must be called for
non-static file requests as well as static files that are being served by the
middleware. That's because there may be cases where a set of static files
must be pushed in association with a non-static resource. For example, when
`index.html` is a non-static file that is dynamically generated by the
application, it probably wants to push related resources such as stylesheets,
images, JavaScript files, etc. that are needed for the browser to render the
page.

When there is an error while pushing resources, a `'pushError'` will be
emitted on the parent `stream`, whose argument is an error object that caused
it.

#### `recordRequestPath()`

```typescript
recordRequestPath(
    session: http2.Http2Session,
    reqPath: string,
    isStatic: boolean): void;
```

This method must be called for every request from the client. It must be
called for non-static file requests as well as static files, as explained for
`preprocessRequest()` above.

*   `session`: The current session object.
*   `reqPath`: The request path given from the client.
*   `isStatic`: `true` if the request is for a static file that is being served
    by the middleware, `false` otherwise.

### `AssetCacheConfig`

This can be passed to the constructor of `AutoPush` to customize the caching
behavior.

```typescript
interface AssetCacheConfig {
  warmupDuration: number;
  promotionRatio: number;
  demotionRatio: number;
  minimumRequests: number;
}
```

#### `warmupDuration`

The time duration (in milliseconds) after a client request during which to
record additional requests. That record will be used for determining the
associated resources that may be pushed for a request path.

#### `promotionRatio`

If an additional request is frequently made for a certain original request
and its hit ratio is over the `promotionRatio` value, that request path is
considered one of the associated resources of the original request, and it'll
be pushed when a request is made for the same original request path later.

#### `demotionRatio`

Similar to `promotionRatio`, but if the hit ratio is lower than
`demotionRatio`, the request path will not be considered an associated
resource anymore.

#### `minimumRequests`

The minimum number of requests for a certain path before being considered as
a candidate for an associated resource.