Browsers now implement high-level request abstractions around fetch, which are very similar to what we have been doing in RESTBase, but add some desirable features like
- streaming requests and responses (incl. 'tee' support),
- optional decoding via text(), json(), blob() accessors.
- 'proper' Map for headers,
- enforcement of cloning, and
- support for redirects.
These APIs are going to be fairly ubiquitous, so I think we should keep an eye on them & evaluate whether we should gradually move towards a fetch like interface in preq and RESTBase.
- Spec: https://fetch.spec.whatwg.org/
- Examples: https://github.com/github/fetch
- Main node implementation: https://github.com/bitinn/node-fetch
- Browser-focused intro articles: https://jakearchibald.com/2015/thats-so-fetch/, https://jakearchibald.com/2016/streams-ftw/
Request object
The fetch request interface differs from preq primarily in
- the positional URL parameter (optional in preq),
- Headers in addition to Object (as with Response), and
- the handling of the body parameter.
Handling POST / GET with query is a bit ugly in plain fetch:
var url = new URL("https://geo.example.org/api"), params = {lat:35.696233, long:139.570431} Object.keys(params).forEach(key => url.searchParams.append(key, params[key])) fetch(url).then(/* … */)
Response object
Instead of the plain Object, return a Response. Major differences are:
- json, text, blob methods for the body, and access to a stream.
- ok & other extra attributes.
- Headers is a Map, not Object.
- The Response needs to be clone()d before reusing it.
- The query attribute is replaced with url.searchParams.
WhatWG streams
Streaming responses let us reduce memory consumption and time to first byte. It is basically a precondition for client-side content composition performance on slow connections, and is now supported in Chrome Canary 50.
Fetch responses are WhatWG streams by default, which are an incompatible evolution from Node's built-in streams. It's still early days, and the spec continues to evolve. There is a node-compatible and well-tested reference implementation written in ES6. The latest version of this does not seem to be available as a node module, but it doesn't look too hard to create one. The main functionality exposed in clients is currently ReadableStream, so we could consider only exposing this interface for now.