🐑 Commons Host




Table of Contents

What problem does this solve?

One of the features introduced by HTTP/2 is Server Push. Difficulty in configuring servers has inhibited widespread adoption by web developers. This declarative HTTP/2 Server Push Manifest format offers a server- and language-agnostic abstraction.

Why declarative rules?

Declarative rules are passive, i.e. they do not require arbitrary code execution. This is ideal for processing by edge services like a CDN nodes, or other static file servers.

Which software supports HTTP/2 Manifests?

This is currently supported by @commonshost/server, a Node.js based static web server. The commons.host static hosting & CDN service also supports it, as it is based on the same server.

This repository contains the @commonshost/manifest NPM package with a generate() JavaScript helper to automatically trace dependencies. It can generate a manifest automatically for any single page app or static site generator. See the API documentation section for details.

Implementors: Please add your implementation to this paragraph by opening a pull request.

Yes, and those too could be generated based on a Server Push manifest. For example, @commonshost/server automatically outputs Link: https://...; rel=preload headers for clients connecting via HTTP/1.1, and uses PUSH_PROMISE frames for HTTP/2 clients.

But those Link headers are arguably a leftover from the HTTP/1 era. Legacy CDN, proxy, and other middlebox support are often limiting factors.

In practice it is unlikely that you can send more than a handful HTTP/1 Link headers. It is much more efficient to use PUSH_PROMISE frames, which are compressed, virtually unlimited in number, and offer more functionality.

Can I still programmatically push assets?

Sure, that is an implementation issue. Your backend web application could emit PUSH_PROMISE frames which an intermediary CDN edge combines with a push manifest.

Does this work with a CDN?

CDNs are ideally suited for server push manifests. Edge nodes can make full use of the think time between the receipt of a browser request and the response from an upstream, origin server.

What about browser support?

The manifest is not applicable to browsers. No real considerations.

All current popular web browsers (Cr/Fx/Sf/Eg) support HTTP/2 Server Push. While some complications, and occasionally bugs, exist, these will be solved faster if more people start using HTTP/2 Server Push.

Which files can be pushed?

Anything goes. All you need is a URL or file name.

Should this be an RFC?

Probably not, since it is an implementation detail for servers and other tools. Parts of it rely on RFCs (URI Templates, HTTP/2 spec) and other "open standards" like JSON (it's complicated) or Bash extglobs (good luck referencing the exact ISO POSIX spec!).


JSON is widely supported by programming languages used on the web.

Why publish this as a spec?

So that, hopefully, other server and tool builders avoid reinventing the wheel. Makes it easier to build tools that target the manifest format rather than specific server or CDN implementations.

Is JavaScript required?

No, the spec is a language-neutral JSON Schema. The JavaScript code is simply a proof-of-concept implementation.

Can I use HTTP/2 Server Push with CORS assets?

Yes, in theory. The manifest allows pushing URIs.

In practice, browser support is still limited. This area is highly experimental with several related proposals currently under consideration at the IETF HTTP-WG.

Are there security considerations?

Servers and CDNs coalescing multiple origins must take care that a manifest's origin is authorised to push CORS assets from other origins.

What about caching?

Caching and other headers to be included in a PUSH_PROMISE frame are not currently part of this spec. Share your thoughts in the issue tracker if you would like to see support for this feature.

What about HTTP methods, status codes, etc?

Currently only pushes in response to a GET request are described in the manifest. However there is nothing technically preventing a future version of the spec from supporting other methods like POST or PUT, or other (pseudo-)headers. Please share your interest in these use-cases on the issue tracker.

Will the server push too much stuff?

That depends on your manifest. With great power comes great responsibility. Protip: Use negated globs (e.g. !/**.*.map) to exclude files.

What if the browser already has some assets in its cache?

When the server pushes a stream, the browser can quickly close it to avoid wasting resources. Unfortunately this still requires a round-trip.

Consider using HTTP/2 Cache Digests. This spec allows browsers to send a condensed list of its cache contents to the server. The server can use this to avoid sending redundant assets.

What about auto-push?

Several attempts have been made at automatically pushing assets, by build-tools scanning for dependencies or by intellgent servers analysing traffic patterns. The result of these can be encoded as manifest rules for portability or caching.

What about stream dependencies and priorities?

Dependencies can be inferred by recursively tracing the manifest rules. For example resource A has a rule that pushes resource B, which pushes resource C in another rule. Now C is a dependency of B which is a dependency of A.

Priorities are explicitly specified on each rule using the priority key. Its value is an integer from 1 to 256 and defaults to 16. This follows the HTTP/2 spec. All pushed resources in a rule share the same priority.

I thought HTTP/2 priority was a client-only feature?

Correct, oh wise one. The priority of HTTP/2 streams is a suggestion by the client that the server may follow. Ultimately, however, it is the server that controls the order of its data frames. This manifest spec introduces a way for web developers to instruct the server on the priority of streams.

I (do/don't) like this

Not really a question. But feel free to share your experience, thoughts, and suggestions on the issue tracker. Open discussion and feedback is most welcome.