snekfetch
Version:
Just do http requests without all that weird nastiness from other libs
88 lines (69 loc) • 1.94 kB
JavaScript
const http = require('http');
const Stream = require('stream');
const EventEmitter = require('events');
const http2 = (() => {
try {
const h2 = require('http2');
if (!h2.constants) throw new Error('DAMN_YOU_NPM_HTTP2');
return h2;
} catch (err) {
return {
constants: {},
connect: () => {
throw new Error('Please run node with --expose-http2 to use the http2 request transport');
},
};
}
})();
const {
HTTP2_HEADER_PATH,
HTTP2_HEADER_METHOD,
HTTP2_HEADER_STATUS,
} = http2.constants;
class Http2Request extends EventEmitter {
constructor(options) {
super();
this.options = options;
this._headers = {
[HTTP2_HEADER_PATH]: options.pathname,
[HTTP2_HEADER_METHOD]: options.method.toUpperCase(),
};
}
setHeader(name, value) {
this._headers[name.toLowerCase()] = value;
}
getHeader(name) {
return this._headers[name];
}
end() {
const options = this.options;
const client = http2.connect(`${options.protocol}//${options.hostname}`);
const req = client.request(this._headers);
const stream = new Stream.PassThrough();
client.once('error', (e) => this.emit('error', e));
client.once('frameError', (e) => this.emit('error', e));
req.once('response', (headers) => {
stream.headers = headers;
stream.statusCode = headers[HTTP2_HEADER_STATUS];
stream.status = http.STATUS_CODES[stream.statusCode];
this.emit('response', stream);
req.on('data', (chunk) => {
if (!stream.push(chunk)) req.pause();
});
req.once('end', () => {
stream.push(null);
client.destroy();
});
stream.once('error', (err) => {
stream.statusCode = 400;
stream.status = err.message;
});
});
req.end();
return req;
}
}
function request(options) {
return new Http2Request(options);
}
module.exports = { request };