Skip to content

Instantly share code, notes, and snippets.

@paambaati
Last active March 1, 2023 00:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save paambaati/5e52b5bc42b2e6eebcfb55213d1853a1 to your computer and use it in GitHub Desktop.
Save paambaati/5e52b5bc42b2e6eebcfb55213d1853a1 to your computer and use it in GitHub Desktop.
Got with HTTP2 support (ALPN negotiation) + Connect settings overrides
const {extend: gotExtend} = require('got');
const http2 = require('http2-wrapper');
const resolveALPN = require('resolve-alpn');
// Taken from https://github.com/nodejs/node/blob/d4c91f28148af8a6c1a95392e5c88cb93d4b61c6/lib/_http_agent.js
//
// throws
// tls.connect({host: 'httpbin.org', port: 443});
//
// doesn't throw
// tls.connect({host: 'httpbin.org', port: 443, servername: 'httpbin.org'});
const calculateServerName = options => {
let servername = options.host;
const hostHeader = options.headers.host;
if (hostHeader) {
// abc => abc
// abc:123 => abc
// [::1] => ::1
// [::1]:123 => ::1
if (hostHeader.startsWith('[')) {
const index = hostHeader.indexOf(']');
if (index === -1) {
// Leading '[', but no ']'. Need to do something...
servername = hostHeader;
} else {
servername = hostHeader.substr(1, index - 1);
}
} else {
servername = hostHeader.split(':', 1)[0];
}
}
return servername;
};
const got = gotExtend({
hooks: {
beforeRequest: [
async options => {
if (options.protocol === 'https:' && !options.request && !options.createConnection) {
const socketOptions = {
...options,
host: options.hostname || options.host,
path: options.socketPath,
port: options.port || 443,
session: options.socketSession,
servername: options.servername || calculateServerName(options),
ALPNProtocols: ['h2', 'http/1.1'],
resolveSocket: true
};
const {alpnProtocol, socket} = await resolveALPN(socketOptions);
if (alpnProtocol === 'h2') {
const randomConnectSettings = {
headerTableSize: 65536,
maxConcurrentStreams: 1000,
initialWindowSize: 6291456,
};
const session = await http2.connect(options.href, randomConnectSettings);
session.unref();
options.request = http2.request({...options, session});
}
options.createConnection = () => socket;
}
}
]
}
});
(async () => {
const {body: h2body} = await got('https://nghttp2.org/httpbin/headers', {json: true});
console.log('HTTP2', h2body);
const {body: h1body} = await got('https://httpbin.org/headers', {json: true});
console.log('HTTP1', h1body);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment