Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

http2: throw better error when accessing unbound socket proxy #22486

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/api/errors.md
Expand Up @@ -1031,6 +1031,12 @@ The `Http2Session` settings canceled.
An attempt was made to connect a `Http2Session` object to a `net.Socket` or
`tls.TLSSocket` that had already been bound to another `Http2Session` object.

<a id="ERR_HTTP2_SOCKET_UNBOUND"></a>
### ERR_HTTP2_SOCKET_UNBOUND

An attempt was made to use the `socket` property of an `Http2Session` that
has already been closed.

<a id="ERR_HTTP2_STATUS_101"></a>
### ERR_HTTP2_STATUS_101

Expand Down
2 changes: 2 additions & 0 deletions lib/internal/errors.js
Expand Up @@ -588,6 +588,8 @@ E('ERR_HTTP2_SESSION_ERROR', 'Session closed with error code %s', Error);
E('ERR_HTTP2_SETTINGS_CANCEL', 'HTTP2 session settings canceled', Error);
E('ERR_HTTP2_SOCKET_BOUND',
'The socket is already bound to an Http2Session', Error);
E('ERR_HTTP2_SOCKET_UNBOUND',
'The socket has been disconnected from the Http2Session', Error);
E('ERR_HTTP2_STATUS_101',
'HTTP status code 101 (Switching Protocols) is forbidden in HTTP/2', Error);
E('ERR_HTTP2_STATUS_INVALID', 'Invalid status code: %s', RangeError);
Expand Down
13 changes: 11 additions & 2 deletions lib/internal/http2/core.js
Expand Up @@ -60,6 +60,7 @@ const {
ERR_HTTP2_SESSION_ERROR,
ERR_HTTP2_SETTINGS_CANCEL,
ERR_HTTP2_SOCKET_BOUND,
ERR_HTTP2_SOCKET_UNBOUND,
ERR_HTTP2_STATUS_101,
ERR_HTTP2_STATUS_INVALID,
ERR_HTTP2_STREAM_CANCEL,
Expand Down Expand Up @@ -685,12 +686,17 @@ const proxySocketHandler = {
throw new ERR_HTTP2_NO_SOCKET_MANIPULATION();
default:
const socket = session[kSocket];
if (socket === undefined)
throw new ERR_HTTP2_SOCKET_UNBOUND();
const value = socket[prop];
return typeof value === 'function' ? value.bind(socket) : value;
}
},
getPrototypeOf(session) {
return Reflect.getPrototypeOf(session[kSocket]);
const socket = session[kSocket];
if (socket === undefined)
throw new ERR_HTTP2_SOCKET_UNBOUND();
return Reflect.getPrototypeOf(socket);
},
set(session, prop, value) {
switch (prop) {
Expand All @@ -706,7 +712,10 @@ const proxySocketHandler = {
case 'write':
throw new ERR_HTTP2_NO_SOCKET_MANIPULATION();
default:
session[kSocket][prop] = value;
const socket = session[kSocket];
if (socket === undefined)
throw new ERR_HTTP2_SOCKET_UNBOUND();
socket[prop] = value;
return true;
}
}
Expand Down
69 changes: 69 additions & 0 deletions test/parallel/test-http2-unbound-socket-proxy.js
@@ -0,0 +1,69 @@
'use strict';

const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');
const http2 = require('http2');
const net = require('net');

const server = http2.createServer();
server.on('stream', common.mustCall((stream) => {
stream.respond();
stream.end('ok');
}));

server.listen(0, common.mustCall(() => {
const client = http2.connect(`http://localhost:${server.address().port}`);
const socket = client.socket;
const req = client.request();
req.resume();
req.on('close', common.mustCall(() => {
client.close();
server.close();

// Tests to make sure accessing the socket proxy fails with an
// informative error.
setImmediate(common.mustCall(() => {
common.expectsError(() => {
socket.example;
}, {
code: 'ERR_HTTP2_SOCKET_UNBOUND'
});
common.expectsError(() => {
socket.example = 1;
}, {
code: 'ERR_HTTP2_SOCKET_UNBOUND'
});
common.expectsError(() => {
socket instanceof net.Socket;
}, {
code: 'ERR_HTTP2_SOCKET_UNBOUND'
});
common.expectsError(() => {
socket.ref();
}, {
code: 'ERR_HTTP2_SOCKET_UNBOUND'
});
common.expectsError(() => {
socket.unref();
}, {
code: 'ERR_HTTP2_SOCKET_UNBOUND'
});
common.expectsError(() => {
socket.setEncoding();
}, {
code: 'ERR_HTTP2_SOCKET_UNBOUND'
});
common.expectsError(() => {
socket.setKeepAlive();
}, {
code: 'ERR_HTTP2_SOCKET_UNBOUND'
});
common.expectsError(() => {
socket.setNoDelay();
}, {
code: 'ERR_HTTP2_SOCKET_UNBOUND'
});
}));
}));
}));