JSPM

  • Created
  • Published
  • Downloads 13887996
  • Score
    100M100P100Q222641F
  • License MIT

HTTP2 client, just with the familiar `https` API

Package Exports

  • http2-wrapper

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (http2-wrapper) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

http2-wrapper

HTTP2 client, just with the familiar https API

Build Status Coverage Status npm install size

This package was created to support HTTP2 without the need to rewrite your code.
I recommend adapting to the http2 module if possible - it's much simpler to use and has many cool features!

Tip: http2-wrapper is very useful when you rely on other modules that use the HTTP1 API and you want to support HTTP2.

Installation

$ npm install http2-wrapper
$ yarn add http2-wrapper

It's best to run http2-wrapper under the latest version of Node. It provides the best stability.

Usage

const http2 = require('http2-wrapper');

const options = {
    hostname: 'nghttp2.org',
    protocol: 'https:',
    path: '/httpbin/post',
    method: 'POST',
    headers: {
        'content-length': 6
    }
};

const request = http2.request(options, response => {
    console.log('statusCode:', response.statusCode);
    console.log('headers:', response.headers);

    const body = [];
    response.on('data', chunk => {
        body.push(chunk);
    });
    response.on('end', () => {
        console.log('body:', Buffer.concat(body).toString());
    });
});

request.on('error', e => console.error(e));

request.write('123');
request.end('456');

// statusCode: 200
// headers: [Object: null prototype] {
//   ':status': 200,
//   date: 'Fri, 27 Sep 2019 19:45:46 GMT',
//   'content-type': 'application/json',
//   'access-control-allow-origin': '*',
//   'access-control-allow-credentials': 'true',
//   'content-length': '239',
//   'x-backend-header-rtt': '0.002516',
//   'strict-transport-security': 'max-age=31536000',
//   server: 'nghttpx',
//   via: '1.1 nghttpx',
//   'alt-svc': 'h3-23=":4433"; ma=3600',
//   'x-frame-options': 'SAMEORIGIN',
//   'x-xss-protection': '1; mode=block',
//   'x-content-type-options': 'nosniff'
// }
// body: {
//   "args": {},
//   "data": "123456",
//   "files": {},
//   "form": {},
//   "headers": {
//     "Content-Length": "6",
//     "Host": "nghttp2.org"
//   },
//   "json": 123456,
//   "origin": "xxx.xxx.xxx.xxx",
//   "url": "https://nghttp2.org/httpbin/post"
// }

API

Note: the session option was renamed to tlsSession for better readability.

http2.auto(url, options, callback)

Performs ALPN negotiation. Returns a Promise giving proper ClientRequest instance (depending on the ALPN).

Tip: the agent option also accepts an object with http, https and http2 properties.

const http2 = require('http2-wrapper');

const options = {
    hostname: 'httpbin.org',
    protocol: 'http:', // Note the `http:` protocol here
    path: '/post',
    method: 'POST',
    headers: {
        'content-length': 6
    }
};

(async () => {
    try {
        const request = await http2.auto(options, response => {
            console.log('statusCode:', response.statusCode);
            console.log('headers:', response.headers);

            const body = [];
            response.on('data', chunk => body.push(chunk));
            response.on('end', () => {
                console.log('body:', Buffer.concat(body).toString());
            });
        });

        request.on('error', console.error);

        request.write('123');
        request.end('456');
    } catch (error) {
        console.error(error);
    }
})();

// statusCode: 200
// headers: { connection: 'close',
//   server: 'gunicorn/19.9.0',
//   date: 'Sat, 15 Dec 2018 18:19:32 GMT',
//   'content-type': 'application/json',
//   'content-length': '259',
//   'access-control-allow-origin': '*',
//   'access-control-allow-credentials': 'true',
//   via: '1.1 vegur' }
// body: {
//   "args": {},
//   "data": "123456",
//   "files": {},
//   "form": {},
//   "headers": {
//     "Connection": "close",
//     "Content-Length": "6",
//     "Host": "httpbin.org"
//   },
//   "json": 123456,
//   "origin": "xxx.xxx.xxx.xxx",
//   "url": "http://httpbin.org/post"
// }

http2.auto.protocolCache

An instance of quick-lru used for ALPN cache.

There is a maximum of 100 entries. You can modify the limit through protocolCache.maxSize - note that the change will be visible globally.

http2.request(url, options, callback)

Same as https.request.

options.preconnect

Type: boolean
Default: true

If set to true, it will try to connect to the server before sending the request.

options.h2session

Type: Http2Session

The session used to make the actual request. If none provided, it will use options.agent.

http2.get(url, options, callback)

Same as https.get.

new http2.ClientRequest(url, options, callback)

Same as https.ClientRequest.

new http2.IncomingMessage(socket)

Same as https.IncomingMessage.

new http2.Agent(options)

Note: this is not compatible with the classic http.Agent.

Usage example:

const http2 = require('http2-wrapper');

class MyAgent extends http2.Agent {
    createConnection(authority, options) {
        console.log(`Connecting to ${authority}`);
        return http2.Agent.connect(authority, options);
    }
}

http2.get({
    hostname: 'google.com',
    agent: new MyAgent()
}, res => {
    res.on('data', chunk => console.log(`Received chunk of ${chunk.length} bytes`));
});

options

Each option is assigned to each Agent instance and can be changed later.

timeout

Type: number
Default: 60000

If there's no activity after timeout milliseconds, the session will be closed.

maxSessions

Type: number
Default: Infinity

The maximum amount of sessions per origin.

maxFreeSessions

Type: number
Default: 1

The maximum amount of free sessions per origin.

maxCachedTlsSessions

Type: number
Default: 100

The maximum amount of cached TLS sessions.

Agent.normalizeAuthority(authority, servername)

Normalizes the authority URL.

Agent.normalizeAuthority('https://example.com:443');
// => 'https://example.com'

Agent.normalizeOptions(options)

Returns a string containing normalized options.

Agent.normalizeOptions({servername: 'example.com'});
// => ':example.com'

agent.settings

Type: object
Default: {enablePush: false}

Settings used by the current agent instance.

agent.getSession(authority, options)

authority

Type: string URL object

Authority used to create a new session.

options

Type: object

Options used to create a new session.

Returns a Promise giving free Http2Session. If no free sessions are found, a new one is created.

agent.getSession(authority, options, listener)

listener

Type: object

{
    reject: error => void,
    resolve: session => void
}

If the listener argument is present, the Promise will resolve immediately. It will use the resolve function to pass the session.

agent.request(authority, options, headers)

Returns a Promise giving Http2Stream.

agent.createConnection(authority, options)

Returns a new TLSSocket. It defaults to Agent.connect(authority, options).

agent.closeFreeSessions()

Makes an attempt to close free sessions. Only sessions with 0 concurrent streams are closed.

agent.destroy(reason)

Destroys all sessions.

Event: 'session'

agent.on('session', session => {
    // A new session has been created by the Agent.
});

Notes

Benchmarks

CPU: Intel i7-7700k
Server: H2O 2.2.5 h2o.conf
Node: 13.0.1

http2-wrapper x 10,943 ops/sec ±4.19% (80 runs sampled)
http2-wrapper - preconfigured session x 13,600 ops/sec ±1.78% (85 runs sampled)
http2-wrapper - auto x 10,080 ops/sec ±4.22% (80 runs sampled)
http2 x 16,078 ops/sec ±1.67% (85 runs sampled)
http2 - using PassThrough proxies x 13,090 ops/sec ±6.36% (85 runs sampled)
https x 1,471 ops/sec ±4.05% (74 runs sampled)
http x 6,100 ops/sec ±4.89% (72 runs sampled)
Fastest is http2

http2-wrapper:

  • It's 1.4692x slower than http2.
  • It's 1.1962x slower than http2 with 2xPassThrough.
  • It's 7.4392x faster than https.
  • It's 1.7939x faster than http.

http2-wrapper - preconfigured session:

  • It's 1.1822x slower than http2.
  • It's almost the same as http2 with 2xPassThrough.
  • It's 9.2454x faster than https.
  • It's 2.2295x faster than http.

http2-wrapper - auto:

  • It's 1.5950x slower than http2.
  • It's 1.2986x slower than http2 with 2xPassThrough.
  • It's 6.8525x faster than https.
  • It's 1.6525x faster than http.
  • got - Simplified HTTP requests

License

MIT