Socket
Socket
Sign inDemoInstall

http2-wrapper

Package Overview
Dependencies
Maintainers
1
Versions
59
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

http2-wrapper - npm Package Compare versions

Comparing version 1.0.0-beta.3 to 1.0.0-beta.4

28

package.json
{
"name": "http2-wrapper",
"version": "1.0.0-beta.3",
"version": "1.0.0-beta.4",
"description": "HTTP2 client, just with the familiar `https` API",

@@ -33,29 +33,25 @@ "main": "source",

"dependencies": {
"quick-lru": "^4.0.1",
"quick-lru": "^5.0.0",
"resolve-alpn": "^1.0.0"
},
"devDependencies": {
"@sindresorhus/is": "^1.0.0",
"ava": "^2.4.0",
"@sindresorhus/is": "^2.0.0",
"ava": "^3.3.0",
"benchmark": "^2.1.4",
"coveralls": "^3.0.5",
"coveralls": "^3.0.9",
"create-cert": "^1.0.6",
"get-stream": "^5.1.0",
"got": "^10.0.0-alpha.3",
"lolex": "^4.2.0",
"got": "^10.5.5",
"lolex": "^6.0.0",
"many-keys-map": "^1.0.2",
"nyc": "^14.1.1",
"nyc": "^15.0.0",
"p-event": "^4.1.0",
"tempy": "^0.3.0",
"tempy": "^0.4.0",
"to-readable-stream": "^2.1.0",
"tsd": "^0.8.0",
"xo": "^0.24.0"
"tsd": "^0.11.0",
"xo": "^0.26.1"
},
"ava": {
"timeout": "2m",
"concurrency": "4",
"helpers": [
"test/helpers/*"
]
"timeout": "2m"
}
}

@@ -10,3 +10,3 @@ # http2-wrapper

This package was created to support HTTP2 without the need to rewrite your code.<br>
I recommend adapting to the [`http2`](https://nodejs.org/api/http2.html) module if possible - it's much simpler to use and has many cool features!
I recommend adapting to the [`http2`](https://nodejs.org/api/http2.html) module if possible - it's much simpler to use and has many cool features! Well, it doesn't have agents yet...

@@ -88,3 +88,3 @@ **Tip**: `http2-wrapper` is very useful when you rely on other modules that use the HTTP1 API and you want to support HTTP2.

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

@@ -96,3 +96,3 @@ ### http2.auto(url, options, callback)

**Tip**: the `agent` option also accepts an object with `http`, `https` and `http2` properties.
**Note**: The `agent` option represents an object with `http`, `https` and `http2` properties.

@@ -204,5 +204,5 @@ ```js

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

@@ -251,15 +251,17 @@ }

#### Agent.normalizeAuthority([authority](#authority), servername)
#### Agent.normalizeOrigin(url)
Normalizes the authority URL.
Returns a string representing the origin of the URL.
```js
Agent.normalizeAuthority('https://example.com:443');
// => 'https://example.com'
```
#### agent.settings
#### Agent.normalizeOptions([options](https://github.com/szmarczak/http2-wrapper/blob/master/source/agent.js))
Type: `object`<br>
Default: `{enablePush: false}`
Returns a string containing normalized options.
[Settings](https://nodejs.org/api/http2.html#http2_settings_object) used by the current agent instance.
#### agent.normalizeOptions([options](https://github.com/szmarczak/http2-wrapper/blob/master/source/agent.js))
Returns a string representing normalized options.
```js

@@ -270,16 +272,9 @@ Agent.normalizeOptions({servername: 'example.com'});

#### agent.settings
#### agent.getSession(origin, options)
Type: `object`<br>
Default: `{enablePush: false}`
##### [origin](https://nodejs.org/api/http2.html#http2_http2_connect_authority_options_listener)
[Settings](https://nodejs.org/api/http2.html#http2_settings_object) used by the current agent instance.
#### agent.getSession(authority, options)
##### [authority](https://nodejs.org/api/http2.html#http2_http2_connect_authority_options_listener)
Type: `string` `URL` `object`
Authority used to create a new session.
An origin used to create new session.

@@ -290,7 +285,7 @@ ##### [options](https://nodejs.org/api/http2.html#http2_http2_connect_authority_options_listener)

Options used to create a new session.
The options used to create new session.
Returns a Promise giving free `Http2Session`. If no free sessions are found, a new one is created.
#### agent.getSession([authority](#authority), [options](options-1), listener)
#### agent.getSession([origin](#origin), [options](options-1), listener)

@@ -310,13 +305,13 @@ ##### listener

#### agent.request([authority](#authority), [options](#options-1), [headers](https://nodejs.org/api/http2.html#http2_headers_object))
#### agent.request([origin](#origin), [options](#options-1), [headers](https://nodejs.org/api/http2.html#http2_headers_object))
Returns a Promise giving `Http2Stream`.
#### agent.createConnection([authority](#authority), [options](#options-1))
#### agent.createConnection([origin](#origin), [options](#options-1))
Returns a new `TLSSocket`. It defaults to `Agent.connect(authority, options)`.
Returns a new `TLSSocket`. It defaults to `Agent.connect(origin, options)`.
#### agent.closeFreeSessions()
Makes an attempt to close free sessions. Only sessions with 0 concurrent streams are closed.
Makes an attempt to close free sessions. Only sessions with 0 concurrent streams will be closed.

@@ -343,14 +338,17 @@ #### agent.destroy(reason)

CPU: Intel i7-7700k<br>
Server: H2O 2.2.5 [`h2o.conf`](h2o.conf)<br>
Node: 13.0.1
CPU: Intel i7-7700k (governor: performance)<br>
Server: H2O v2.2.5 [`h2o.conf`](h2o.conf)<br>
Node: v13.8.0
`auto` means `http2wrapper.auto`.
```
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)
http2-wrapper x 12,417 ops/sec ±3.72% (83 runs sampled)
http2-wrapper - preconfigured session x 14,517 ops/sec ±1.39% (83 runs sampled)
http2-wrapper - auto x 11,373 ops/sec ±3.17% (84 runs sampled)
http2 x 16,172 ops/sec ±1.21% (85 runs sampled)
https - auto - keepalive x 13,251 ops/sec ±3.84% (79 runs sampled)
https - keepalive x 13,158 ops/sec ±2.88% (78 runs sampled)
https x 1,618 ops/sec ±2.07% (82 runs sampled)
http x 5,922 ops/sec ±2.87% (79 runs sampled)
Fastest is http2

@@ -360,21 +358,20 @@ ```

`http2-wrapper`:
- 23% less performant than `http2`
- 6% less performant than `https - keepalive`
- 110% more performant than `http`
- 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`:
- 10% less performant than `http2`
- 10% more performant than `https - keepalive`
- 145% more performant than `http`
- 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`:
- 30% less performant than `http2`
- 14% less performant than `https - keepalive`
- 92% more performant than `http`
- 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`.
`https - auto - keepalive`:
- 18% less performant than `http2`
- as performant as `https - keepalive`
- 124% more performant than `http`

@@ -381,0 +378,0 @@ ## Related

@@ -9,2 +9,3 @@ 'use strict';

const kRequest = Symbol('request');
const kOriginSet = Symbol('cachedOriginSet');

@@ -72,6 +73,6 @@ const nameKeys = [

const getSessions = (where, name, normalizedAuthority) => {
const getSessions = (where, name, normalizedOrigin) => {
if (Reflect.has(where, name)) {
return where[name].filter(session => {
return !session.closed && !session.destroyed && session.originSet.includes(normalizedAuthority);
return !session.closed && !session.destroyed && session[kOriginSet].includes(normalizedOrigin);
});

@@ -95,6 +96,6 @@ }

// The set is a proper subset when its length is less than the other set.
coveredSession.originSet.length < session.originSet.length &&
coveredSession[kOriginSet].length < session[kOriginSet].length &&
// And the other set includes all elements of the subset.
coveredSession.originSet.every(origin => session.originSet.includes(origin)) &&
coveredSession[kOriginSet].every(origin => session[kOriginSet].includes(origin)) &&

@@ -115,4 +116,4 @@ // Makes sure that the session can handle all requests from the covered session.

if (
coveredSession.originSet.length < session.originSet.length &&
coveredSession.originSet.every(origin => session.originSet.includes(origin)) &&
coveredSession[kOriginSet].length < session[kOriginSet].length &&
coveredSession[kOriginSet].every(origin => session[kOriginSet].includes(origin)) &&
coveredSession[kCurrentStreamsCount] + session[kCurrentStreamsCount] <= session.remoteSettings.maxConcurrentStreams

@@ -138,3 +139,3 @@ ) {

// The queue for creating new sessions. It looks like this:
// QUEUE[NORMALIZED_OPTIONS][NORMALIZED_AUTHORITY] = ENTRY_FUNCTION
// QUEUE[NORMALIZED_OPTIONS][NORMALIZED_ORIGIN] = ENTRY_FUNCTION
//

@@ -167,18 +168,11 @@ // The entry function has `listeners`, `completed` and `destroyed` properties.

static normalizeAuthority(authority, servername) {
if (typeof authority === 'string') {
authority = new URL(authority);
static normalizeOrigin(url, servername) {
if (typeof url === 'string') {
url = new URL(url);
}
const host = servername || authority.hostname || authority.host || 'localhost';
const port = authority.port || 443;
if (port === 443) {
return `https://${host}`;
}
return `https://${host}:${port}`;
return servername ? `https://${servername}:${url.port || 443}` : url.origin;
}
static normalizeOptions(options) {
normalizeOptions(options) {
let normalized = '';

@@ -197,4 +191,4 @@

_tryToCreateNewSession(normalizedOptions, normalizedAuthority) {
if (!Reflect.has(this.queue, normalizedOptions) || !Reflect.has(this.queue[normalizedOptions], normalizedAuthority)) {
_tryToCreateNewSession(normalizedOptions, normalizedOrigin) {
if (!Reflect.has(this.queue, normalizedOptions) || !Reflect.has(this.queue[normalizedOptions], normalizedOrigin)) {
return;

@@ -204,4 +198,4 @@ }

// We need the busy sessions length to check if a session can be created.
const busyLength = getSessions(this.busySessions, normalizedOptions, normalizedAuthority).length;
const item = this.queue[normalizedOptions][normalizedAuthority];
const busyLength = getSessions(this.busySessions, normalizedOptions, normalizedOrigin).length;
const item = this.queue[normalizedOptions][normalizedOrigin];

@@ -221,3 +215,3 @@ // The entry function can be run only once.

getSession(authority, options, listeners) {
getSession(origin, options, listeners) {
return new Promise((resolve, reject) => {

@@ -234,8 +228,13 @@ if (Array.isArray(listeners)) {

const normalizedOptions = Agent.normalizeOptions(options);
const normalizedAuthority = Agent.normalizeAuthority(authority, options && options.servername);
const normalizedOptions = this.normalizeOptions(options);
const normalizedOrigin = Agent.normalizeOrigin(origin, options && options.servername);
if (normalizedOrigin === undefined) {
reject(new TypeError('The `origin` argument needs to be a string or an URL object'));
return;
}
if (Reflect.has(this.freeSessions, normalizedOptions)) {
// Look for all available free sessions.
const freeSessions = getSessions(this.freeSessions, normalizedOptions, normalizedAuthority);
const freeSessions = getSessions(this.freeSessions, normalizedOptions, normalizedOrigin);

@@ -264,5 +263,5 @@ if (freeSessions.length !== 0) {

if (Reflect.has(this.queue, normalizedOptions)) {
if (Reflect.has(this.queue[normalizedOptions], normalizedAuthority)) {
if (Reflect.has(this.queue[normalizedOptions], normalizedOrigin)) {
// There's already an item in the queue, just attach ourselves to it.
this.queue[normalizedOptions][normalizedAuthority].listeners.push(...listeners);
this.queue[normalizedOptions][normalizedOrigin].listeners.push(...listeners);

@@ -280,4 +279,4 @@ return;

// Our entry can be replaced. We cannot remove the new one.
if (Reflect.has(this.queue, normalizedOptions) && this.queue[normalizedOptions][normalizedAuthority] === entry) {
delete this.queue[normalizedOptions][normalizedAuthority];
if (Reflect.has(this.queue, normalizedOptions) && this.queue[normalizedOptions][normalizedOrigin] === entry) {
delete this.queue[normalizedOptions][normalizedOrigin];

@@ -292,3 +291,3 @@ if (Object.keys(this.queue[normalizedOptions]).length === 0) {

const entry = () => {
const name = `${normalizedAuthority}:${normalizedOptions}`;
const name = `${normalizedOrigin}:${normalizedOptions}`;
let receivedSettings = false;

@@ -300,3 +299,3 @@ let servername;

const session = http2.connect(authority, {
const session = http2.connect(origin, {
createConnection: this.createConnection,

@@ -312,3 +311,3 @@ settings: this.settings,

// Fetch the smallest amount of free sessions of any origin we have.
const freeSessionsCount = session.originSet.reduce((accumulator, origin) => {
const freeSessionsCount = session[kOriginSet].reduce((accumulator, origin) => {
return Math.min(accumulator, getSessions(this.freeSessions, normalizedOptions, origin).length);

@@ -383,3 +382,3 @@ }, Infinity);

// There may be another session awaiting.
this._tryToCreateNewSession(normalizedOptions, normalizedAuthority);
this._tryToCreateNewSession(normalizedOptions, normalizedOrigin);
});

@@ -393,3 +392,3 @@

for (const origin of session.originSet) {
for (const origin of session[kOriginSet]) {
if (Reflect.has(this.queue[normalizedOptions], origin)) {

@@ -424,2 +423,4 @@ const {listeners} = this.queue[normalizedOptions][origin];

session.once('origin', () => {
session[kOriginSet] = session.originSet;
if (!isFree()) {

@@ -454,2 +455,3 @@ // The session is full.

session[kOriginSet] = session.originSet;
this.emit('session', session);

@@ -477,3 +479,3 @@

// Request for a new session with predefined listeners.
this.getSession(normalizedAuthority, options, listeners);
this.getSession(normalizedOrigin, options, listeners);
listeners.length = 0;

@@ -557,10 +559,10 @@ }

this.queue[normalizedOptions][normalizedAuthority] = entry;
this._tryToCreateNewSession(normalizedOptions, normalizedAuthority);
this.queue[normalizedOptions][normalizedOrigin] = entry;
this._tryToCreateNewSession(normalizedOptions, normalizedOrigin);
});
}
request(authority, options, headers) {
request(origin, options, headers) {
return new Promise((resolve, reject) => {
this.getSession(authority, options, [{
this.getSession(origin, options, [{
reject,

@@ -574,11 +576,11 @@ resolve: session => {

createConnection(authority, options) {
return Agent.connect(authority, options);
createConnection(origin, options) {
return Agent.connect(origin, options);
}
static connect(authority, options) {
static connect(origin, options) {
options.ALPNProtocols = ['h2'];
const port = authority.port || 443;
const host = authority.hostname || authority.host;
const port = origin.port || 443;
const host = origin.hostname || origin.host;

@@ -585,0 +587,0 @@ if (typeof options.servername === 'undefined') {

@@ -11,3 +11,31 @@ 'use strict';

const cache = new QuickLRU({maxSize: 100});
const queue = new Map();
const installSocket = (agent, socket, options) => {
socket._httpMessage = {shouldKeepAlive: true};
const onFree = () => {
agent.emit('free', socket, options);
};
socket.on('free', onFree);
const onClose = () => {
agent.removeSocket(socket, options);
};
socket.on('close', onClose);
const onRemove = () => {
agent.removeSocket(socket, options);
socket.off('close', onClose);
socket.off('free', onFree);
socket.off('agentRemove', onRemove);
};
socket.on('agentRemove', onRemove);
agent.emit('free', socket, options);
};
const resolveProtocol = async options => {

@@ -17,6 +45,42 @@ const name = `${options.host}:${options.port}:${options.ALPNProtocols.sort()}`;

if (!cache.has(name)) {
const result = (await resolveALPN(options)).alpnProtocol;
cache.set(name, result);
if (queue.has(name)) {
const result = await queue.get(name);
return result.alpnProtocol;
}
return result;
const {path} = options;
options.path = options.socketPath;
const resultPromise = resolveALPN(options);
queue.set(name, resultPromise);
try {
const {socket, alpnProtocol} = await resultPromise;
cache.set(name, alpnProtocol);
options.path = path;
if (alpnProtocol === 'h2') {
// TODO: Reuse socket
socket.end();
} else {
const agent = options.agent || https.globalAgent;
if (options.createConnection) {
socket.end();
} else if (agent.keepAlive) {
installSocket(agent, socket, options);
} else {
options.createConnection = () => socket;
}
}
queue.delete(name);
return alpnProtocol;
} catch (error) {
queue.delete(name);
throw error;
}
}

@@ -34,2 +98,3 @@

callback = options;
options = undefined;
}

@@ -42,22 +107,28 @@

...options,
resolveSocket: false
resolveSocket: true
};
const isHttps = options.protocol === 'https:';
const agents = options.agent;
options.host = options.hostname || options.host || 'localhost';
options.session = options.tlsSession;
options.servername = options.servername || calculateServerName(options);
options.port = options.port || (isHttps ? 443 : 80);
options._defaultAgent = isHttps ? https.globalAgent : http.globalAgent;
if (options.protocol === 'https:') {
options.port = options.port || 443;
if (agents) {
if (agents.addRequest) {
throw new Error('The `options.agent` object can contain only `http`, `https` or `http2` properties');
}
const {path} = options;
options.path = options.socketPath;
options.agent = agents[isHttps ? 'https' : 'http'];
}
if (isHttps) {
const protocol = await resolveProtocol(options);
options.path = path;
if (protocol === 'h2') {
if (options.agent && options.agent.http2) {
options.agent = options.agent.http2;
if (agents) {
options.agent = agents.http2;
}

@@ -67,20 +138,4 @@

}
if (options.agent && options.agent.https) {
options.agent = options.agent.https;
}
options._defaultAgent = https.globalAgent;
return http.request(options, callback);
}
options.port = options.port || 80;
if (options.agent && options.agent.http) {
options.agent = options.agent.http;
}
options._defaultAgent = http.globalAgent;
return http.request(options, callback);

@@ -87,0 +142,0 @@ };

@@ -26,3 +26,3 @@ 'use strict';

const kHeaders = Symbol('headers');
const kAuthority = Symbol('authority');
const kOrigin = Symbol('origin');
const kSession = Symbol('session');

@@ -33,3 +33,3 @@ const kOptions = Symbol('options');

const isValidHttpToken = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/;
const isInvalidHeaderValue = /[^\t\u0020-\u007e\u0080-\u00ff]/;
const isInvalidHeaderValue = /[^\t\u0020-\u007E\u0080-\u00FF]/;

@@ -45,3 +45,3 @@ class ClientRequest extends Writable {

if (typeof options === 'function') {
if (typeof options === 'function' || options === undefined) {
// (options, callback)

@@ -84,3 +84,3 @@ callback = options;

const {timeout} = options;
delete options.timeout;
options.timeout = undefined;

@@ -113,10 +113,12 @@ this[kHeaders] = Object.create(null);

this[kOptions] = options;
this[kAuthority] = Agent.normalizeAuthority(options, options.servername);
if (!Reflect.has(this[kHeaders], ':authority')) {
this[kHeaders][':authority'] = this[kAuthority].slice(8);
this[kHeaders][':authority'] = `${options.servername || options.host}:${options.port}`;
}
options.origin = `https://${options.host}:${options.port}`;
this[kOrigin] = options;
if (this.agent && options.preconnect !== false) {
this.agent.getSession(this[kAuthority], options).catch(() => {});
this.agent.getSession(this[kOrigin], options).catch(() => {});
}

@@ -135,2 +137,6 @@

get method() {
return this[kHeaders][HTTP2_HEADER_METHOD];
}
set method(value) {

@@ -142,4 +148,4 @@ if (value) {

get method() {
return this[kHeaders][HTTP2_HEADER_METHOD];
get path() {
return this[kHeaders][HTTP2_HEADER_PATH];
}

@@ -153,6 +159,2 @@

get path() {
return this[kHeaders][HTTP2_HEADER_PATH];
}
_write(chunk, encoding, callback) {

@@ -208,3 +210,3 @@ this.flushHeaders();

flushHeaders() {
async flushHeaders() {
if (this[kFlushedHeaders] || this.destroyed || this.aborted) {

@@ -223,3 +225,3 @@ return;

if (this.destroyed || this.aborted) {
this._request.close(NGHTTP2_CANCEL);
stream.close(NGHTTP2_CANCEL);
return;

@@ -230,21 +232,23 @@ }

if (!isConnectMethod) {
proxyEvents(this._request, this, ['timeout', 'continue', 'close', 'error']);
proxyEvents(stream, this, ['timeout', 'continue', 'close', 'error']);
}
// This event tells we are ready to listen for the data.
this._request.once('response', (headers, flags, rawHeaders) => {
stream.once('response', (headers, flags, rawHeaders) => {
// If we were to emit raw request stream, it would be as fast as the native approach.
// Note that wrapping the raw stream in a Proxy instance won't improve the performance (already tested it).
this.res = new IncomingMessage(this.socket, this._request.readableHighWaterMark);
this.res.req = this;
this.res.statusCode = headers[HTTP2_HEADER_STATUS];
this.res.headers = headers;
this.res.rawHeaders = rawHeaders;
const response = new IncomingMessage(this.socket, stream.readableHighWaterMark);
this.res = response;
this.res.once('end', () => {
response.req = this;
response.statusCode = headers[HTTP2_HEADER_STATUS];
response.headers = headers;
response.rawHeaders = rawHeaders;
response.once('end', () => {
if (this.aborted) {
this.res.aborted = true;
this.res.emit('aborted');
response.aborted = true;
response.emit('aborted');
} else {
this.res.complete = true;
response.complete = true;
}

@@ -254,19 +258,27 @@ });

if (isConnectMethod) {
this.res.upgrade = true;
response.upgrade = true;
// The HTTP1 API says the socket is detached here,
// but we can't do that so we pass the original HTTP2 request.
if (this.emit('connect', this.res, this._request, Buffer.alloc(0))) {
if (this.emit('connect', response, stream, Buffer.alloc(0))) {
this.emit('close');
} else {
// No listeners attached, destroy the original request.
this._request.destroy();
stream.destroy();
}
} else {
// Forwards data
this._request.pipe(this.res);
stream.on('data', chunk => {
if (!response.push(chunk)) {
this.pause();
}
});
if (!this.emit('response', this.res)) {
stream.once('end', () => {
response.push(null);
});
if (!this.emit('response', response)) {
// No listeners attached, dump the response.
this.res._dump();
response._dump();
}

@@ -277,5 +289,5 @@ }

// Emits `information` event
this._request.once('headers', headers => this.emit('information', {statusCode: headers[HTTP2_HEADER_STATUS]}));
stream.once('headers', headers => this.emit('information', {statusCode: headers[HTTP2_HEADER_STATUS]}));
this._request.once('trailers', (trailers, flags, rawTrailers) => {
stream.once('trailers', (trailers, flags, rawTrailers) => {
// Assigns trailers to the response object.

@@ -286,4 +298,4 @@ this.res.trailers = trailers;

this.socket = this._request.session.socket;
this.connection = this._request.session.socket;
this.socket = stream.session.socket;
this.connection = stream.session.socket;

@@ -307,6 +319,7 @@ process.nextTick(() => {

// eslint-disable-next-line promise/prefer-await-to-then
this.agent.request(this[kAuthority], this[kOptions], this[kHeaders]).then(onStream, error => {
try {
onStream(await this.agent.request(this[kOrigin], this[kOptions], this[kHeaders]));
} catch (error) {
this.emit('error', error);
});
}
}

@@ -313,0 +326,0 @@ }

'use strict';
const {PassThrough} = require('stream');
const {Readable} = require('stream');
class IncomingMessage extends PassThrough {
class IncomingMessage extends Readable {
constructor(socket, highWaterMark) {

@@ -47,4 +47,10 @@ super({highWaterMark});

}
_read() {
if (this.req) {
this.req._request.resume();
}
}
}
module.exports = IncomingMessage;

@@ -21,3 +21,3 @@ 'use strict';

if (isManyTypes) {
valid = `${valid.slice(0, valid.length - 1).join(', ')} or ${valid[valid.length - 1]}`;
valid = `${valid.slice(0, -1).join(', ')} or ${valid.slice(-1)}`;
}

@@ -24,0 +24,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc