http2.js-client
Version:
Patch http2-client to use custom http2.js (node-http2)
111 lines (110 loc) • 4.65 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const import_locals_1 = __importDefault(require("import-locals"));
const patcher = new import_locals_1.default(module);
patcher.export('http2-client/lib/request', 'HEADERS_TO_REMOVE');
const request_1 = require("http2-client/lib/request");
const http2_js_1 = require("http2.js");
const endpoint_1 = require("http2.js/lib/protocol/endpoint");
const noop_1 = require("./noop");
class PatchedClass {
holdConnectionToIdentification(clientKey, requestOptions, cb) {
const topic = `identify-${clientKey}`;
if (this._events[topic]) {
this.once(topic, cb);
return;
}
const socket = this.identifyConnection(requestOptions, (type) => {
const options = {
createConnection() {
return socket;
}
};
if (type === 'h2' && this.http2Support) {
const endpoint = new endpoint_1.Endpoint(noop_1.noopLog, 'CLIENT' /* settings */);
endpoint.socket = socket;
endpoint.pipe(endpoint.socket).pipe(endpoint);
this.setHttp2Client(clientKey, endpoint);
}
else {
this.cachedHTTP1Result[clientKey] = Date.now();
}
cb(options);
this.emit(topic, options);
});
}
makeHttp2Request(clientKey, inStream, endpoint, requestOptions, cb) {
const http2Debouncer = this.http2Debouncer;
http2Debouncer.pause(clientKey);
const stream = endpoint.createStream();
const req = new http2_js_1.OutgoingRequest(noop_1.noopLog);
req.stream = stream;
req.options = requestOptions;
req.endpoint = endpoint;
for (const [name, value] of Object.entries(requestOptions.headers || {})) {
req.setHeader(name, value);
}
const headers = req._headers;
for (const name of request_1.HEADERS_TO_REMOVE)
delete headers[name];
if (!headers[':authority']) {
headers[':authority'] = requestOptions.hostname || requestOptions.host;
if (requestOptions.port) {
headers[':authority'] += `:${requestOptions.port}`;
}
}
if (!headers[':method']) {
headers[':method'] = (requestOptions.method || 'GET').toUpperCase();
}
if (!headers[':path']) {
headers[':path'] = requestOptions.path || '/';
}
if (!headers[':scheme']) {
headers[':scheme'] = requestOptions.protocol.slice(0, -1) || 'https';
}
if (!headers['accept-encoding']) {
headers['accept-encoding'] = 'gzip';
}
if (requestOptions.auth) {
headers.authorization =
'Basic ' + Buffer.from(requestOptions.auth).toString('base64');
}
requestOptions.headers = headers;
stream.headers(headers);
inStream.emit('socket', requestOptions.createConnection());
let maxContentLength = 0;
let currentContent = 0;
stream.on('data', data => {
currentContent += data.length;
if (currentContent >= maxContentLength) {
http2Debouncer.unpauseAndTime(clientKey);
}
});
const res = new http2_js_1.IncomingResponse(stream);
res.req = req;
res.once('ready', () => stream.emit('response', res.headers));
inStream.take(stream);
const onResponse = $headers => {
maxContentLength = +$headers['content-length'];
if (isNaN(maxContentLength) || maxContentLength <= 0) {
http2Debouncer.unpauseAndTime(clientKey);
}
request_1.HttpRequestManager.httpCompatibleResponse(res, requestOptions, $headers);
inStream.emit('http1.response', res);
if (cb)
cb(res);
};
stream.on('response', Object.assign(onResponse, { http2Safe: true }));
if (['GET', 'HEAD', 'DELETE'].includes(headers[':method']))
stream.end();
}
}
if (!request_1.HttpRequestManager.$patched) {
request_1.HttpRequestManager.$patched = true;
for (const [name, value] of Object.entries(PatchedClass.prototype)) {
request_1.HttpRequestManager.prototype[name] = value;
}
}