135 lines
6.4 KiB
Markdown
135 lines
6.4 KiB
Markdown
|
# stream-http [![Build Status](https://travis-ci.org/jhiesey/stream-http.svg?branch=master)](https://travis-ci.org/jhiesey/stream-http)
|
||
|
|
||
|
[![Sauce Test Status](https://saucelabs.com/browser-matrix/stream-http.svg)](https://saucelabs.com/u/stream-http)
|
||
|
|
||
|
This module is an implementation of Node's native `http` module for the browser.
|
||
|
It tries to match Node's API and behavior as closely as possible, but some features
|
||
|
aren't available, since browsers don't give nearly as much control over requests.
|
||
|
|
||
|
This is heavily inspired by, and intended to replace, [http-browserify](https://github.com/substack/http-browserify).
|
||
|
|
||
|
## What does it do?
|
||
|
|
||
|
In accordance with its name, `stream-http` tries to provide data to its caller before
|
||
|
the request has completed whenever possible.
|
||
|
|
||
|
The following browsers support true streaming, where only a small amount of the request
|
||
|
has to be held in memory at once:
|
||
|
* Chrome >= 43 (using the `fetch` API)
|
||
|
* Firefox >= 9 (using `moz-chunked-arraybuffer` responseType with xhr)
|
||
|
|
||
|
The following browsers support pseudo-streaming, where the data is available before the
|
||
|
request finishes, but the entire response must be held in memory:
|
||
|
* Chrome
|
||
|
* Safari >= 5, and maybe older
|
||
|
* IE >= 10
|
||
|
* Most other Webkit-based browsers, including the default Android browser
|
||
|
|
||
|
All browsers newer than IE8 support binary responses. All of the above browsers that
|
||
|
support true streaming or pseudo-streaming support that for binary data as well
|
||
|
except for IE10. Old (presto-based) Opera also does not support binary streaming either.
|
||
|
|
||
|
### IE8 note:
|
||
|
As of version 2.0.0, IE8 support requires the user to supply polyfills for
|
||
|
`Object.keys`, `Array.prototype.forEach`, and `Array.prototype.indexOf`. Example
|
||
|
implementations are provided in [ie8-polyfill.js](ie8-polyfill.js); alternately,
|
||
|
you may want to consider using [es5-shim](https://github.com/es-shims/es5-shim).
|
||
|
All browsers with full ES5 support shouldn't require any polyfills.
|
||
|
|
||
|
## How do you use it?
|
||
|
|
||
|
The intent is to have the same API as the client part of the
|
||
|
[Node HTTP module](https://nodejs.org/api/http.html). The interfaces are the same wherever
|
||
|
practical, although limitations in browsers make an exact clone of the Node API impossible.
|
||
|
|
||
|
This module implements `http.request`, `http.get`, and most of `http.ClientRequest`
|
||
|
and `http.IncomingMessage` in addition to `http.METHODS` and `http.STATUS_CODES`. See the
|
||
|
Node docs for how these work.
|
||
|
|
||
|
### Extra features compared to Node
|
||
|
|
||
|
* The `message.url` property provides access to the final URL after all redirects. This
|
||
|
is useful since the browser follows all redirects silently, unlike Node. It is available
|
||
|
in Chrome 37 and newer, Firefox 32 and newer, and Safari 9 and newer.
|
||
|
|
||
|
* The `options.withCredentials` boolean flag, used to indicate if the browser should send
|
||
|
cookies or authentication information with a CORS request. Default false.
|
||
|
|
||
|
This module has to make some tradeoffs to support binary data and/or streaming. Generally,
|
||
|
the module can make a fairly good decision about which underlying browser features to use,
|
||
|
but sometimes it helps to get a little input from the developer.
|
||
|
|
||
|
* The `options.mode` field passed into `http.request` or `http.get` can take on one of the
|
||
|
following values:
|
||
|
* 'default' (or any falsy value, including `undefined`): Try to provide partial data before
|
||
|
the request completes, but not at the cost of correctness for binary data or correctness of
|
||
|
the 'content-type' response header. This mode will also avoid slower code paths whenever
|
||
|
possible, which is particularly useful when making large requests in a browser like Safari
|
||
|
that has a weaker JavaScript engine.
|
||
|
* 'allow-wrong-content-type': Provides partial data in more cases than 'default', but
|
||
|
at the expense of causing the 'content-type' response header to be incorrectly reported
|
||
|
(as 'text/plain; charset=x-user-defined') in some browsers, notably Safari and Chrome 42
|
||
|
and older. Preserves binary data whenever possible. In some cases the implementation may
|
||
|
also be a bit slow. This was the default in versions of this module before 1.5.
|
||
|
* 'prefer-stream': Provide data before the request completes even if binary data (anything
|
||
|
that isn't a single-byte ASCII or UTF8 character) will be corrupted. Of course, this option
|
||
|
is only safe for text data. May also cause the 'content-type' response header to be
|
||
|
incorrectly reported (as 'text/plain; charset=x-user-defined').
|
||
|
* 'disable-fetch': Force the use of plain XHR regardless of the browser declaring a fetch
|
||
|
capability. Preserves the correctness of binary data and the 'content-type' response header.
|
||
|
* 'prefer-fast': Deprecated; now a synonym for 'default', which has the same performance
|
||
|
characteristics as this mode did in versions before 1.5.
|
||
|
|
||
|
### Features missing compared to Node
|
||
|
|
||
|
* `http.Agent` is only a stub
|
||
|
* The 'socket', 'connect', 'upgrade', and 'continue' events on `http.ClientRequest`.
|
||
|
* Any operations, including `request.setTimeout`, that operate directly on the underlying
|
||
|
socket.
|
||
|
* Any options that are disallowed for security reasons. This includes setting or getting
|
||
|
certain headers.
|
||
|
* `message.httpVersion`
|
||
|
* `message.rawHeaders` is modified by the browser, and may not quite match what is sent by
|
||
|
the server.
|
||
|
* `message.trailers` and `message.rawTrailers` will remain empty.
|
||
|
* Redirects are followed silently by the browser, so it isn't possible to access the 301/302
|
||
|
redirect pages.
|
||
|
* The `timeout` options in the `request` method is non-operational in Safari <= 5 and
|
||
|
Opera <= 12.
|
||
|
|
||
|
## Example
|
||
|
|
||
|
``` js
|
||
|
http.get('/bundle.js', function (res) {
|
||
|
var div = document.getElementById('result');
|
||
|
div.innerHTML += 'GET /beep<br>';
|
||
|
|
||
|
res.on('data', function (buf) {
|
||
|
div.innerHTML += buf;
|
||
|
});
|
||
|
|
||
|
res.on('end', function () {
|
||
|
div.innerHTML += '<br>__END__';
|
||
|
});
|
||
|
})
|
||
|
```
|
||
|
|
||
|
## Running tests
|
||
|
|
||
|
There are two sets of tests: the tests that run in Node (found in `test/node`) and the tests
|
||
|
that run in the browser (found in `test/browser`). Normally the browser tests run on
|
||
|
[Sauce Labs](http://saucelabs.com/).
|
||
|
|
||
|
Running `npm test` will run both sets of tests, but in order for the Sauce Labs tests to run
|
||
|
you will need to sign up for an account (free for open source projects) and put the
|
||
|
credentials in a [`.zuulrc` file](https://github.com/defunctzombie/zuul/wiki/zuulrc).
|
||
|
|
||
|
To run just the Node tests, run `npm run test-node`.
|
||
|
|
||
|
To run the browser tests locally, run `npm run test-browser-local` and point your browser to
|
||
|
`http://localhost:8080/__zuul`
|
||
|
|
||
|
## License
|
||
|
|
||
|
MIT. Copyright (C) John Hiesey and other contributors.
|