mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 13:09:21 +01:00
http2: add server handshake utility
PR-URL: https://github.com/nodejs/node/pull/51172 Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
This commit is contained in:
parent
d44814ca68
commit
c50524a9fc
@ -2890,6 +2890,19 @@ added: v8.4.0
|
||||
Returns a [HTTP/2 Settings Object][] containing the deserialized settings from
|
||||
the given `Buffer` as generated by `http2.getPackedSettings()`.
|
||||
|
||||
### `http2.performServerHandshake(socket[, options])`
|
||||
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
* `socket` {stream.Duplex}
|
||||
* `options` {Object}
|
||||
* ...: Any [`http2.createServer()`][] option can be provided.
|
||||
* Returns: {ServerHttp2Session}
|
||||
|
||||
Create an HTTP/2 server session from an existing socket.
|
||||
|
||||
### `http2.sensitiveHeaders`
|
||||
|
||||
<!-- YAML
|
||||
|
@ -8,6 +8,7 @@ const {
|
||||
getDefaultSettings,
|
||||
getPackedSettings,
|
||||
getUnpackedSettings,
|
||||
performServerHandshake,
|
||||
sensitiveHeaders,
|
||||
Http2ServerRequest,
|
||||
Http2ServerResponse,
|
||||
@ -21,6 +22,7 @@ module.exports = {
|
||||
getDefaultSettings,
|
||||
getPackedSettings,
|
||||
getUnpackedSettings,
|
||||
performServerHandshake,
|
||||
sensitiveHeaders,
|
||||
Http2ServerRequest,
|
||||
Http2ServerResponse,
|
||||
|
@ -1228,12 +1228,6 @@ class Http2Session extends EventEmitter {
|
||||
constructor(type, options, socket) {
|
||||
super();
|
||||
|
||||
if (!socket._handle || !socket._handle.isStreamBase) {
|
||||
socket = new JSStreamSocket(socket);
|
||||
}
|
||||
socket.on('error', socketOnError);
|
||||
socket.on('close', socketOnClose);
|
||||
|
||||
// No validation is performed on the input parameters because this
|
||||
// constructor is not exported directly for users.
|
||||
|
||||
@ -1245,6 +1239,12 @@ class Http2Session extends EventEmitter {
|
||||
|
||||
socket[kSession] = this;
|
||||
|
||||
if (!socket._handle || !socket._handle.isStreamBase) {
|
||||
socket = new JSStreamSocket(socket);
|
||||
}
|
||||
socket.on('error', socketOnError);
|
||||
socket.on('close', socketOnClose);
|
||||
|
||||
this[kState] = {
|
||||
destroyCode: NGHTTP2_NO_ERROR,
|
||||
flags: SESSION_FLAGS_PENDING,
|
||||
@ -1644,7 +1644,7 @@ class ServerHttp2Session extends Http2Session {
|
||||
// not be an issue in practice. Additionally, the 'priority' event on
|
||||
// server instances (or any other object) is fully undocumented.
|
||||
this[kNativeFields][kSessionPriorityListenerCount] =
|
||||
server.listenerCount('priority');
|
||||
server ? server.listenerCount('priority') : 0;
|
||||
}
|
||||
|
||||
get server() {
|
||||
@ -3435,6 +3435,11 @@ function getUnpackedSettings(buf, options = kEmptyObject) {
|
||||
return settings;
|
||||
}
|
||||
|
||||
function performServerHandshake(socket, options = {}) {
|
||||
options = initializeOptions(options);
|
||||
return new ServerHttp2Session(options, socket, undefined);
|
||||
}
|
||||
|
||||
binding.setCallbackFunctions(
|
||||
onSessionInternalError,
|
||||
onPriority,
|
||||
@ -3458,6 +3463,7 @@ module.exports = {
|
||||
getDefaultSettings,
|
||||
getPackedSettings,
|
||||
getUnpackedSettings,
|
||||
performServerHandshake,
|
||||
sensitiveHeaders: kSensitiveHeaders,
|
||||
Http2Session,
|
||||
Http2Stream,
|
||||
|
@ -17,6 +17,7 @@ let debug = require('internal/util/debuglog').debuglog(
|
||||
);
|
||||
const { owner_symbol } = require('internal/async_hooks').symbols;
|
||||
const { ERR_STREAM_WRAP } = require('internal/errors').codes;
|
||||
const { kSession } = require('internal/stream_base_commons');
|
||||
|
||||
const kCurrentWriteRequest = Symbol('kCurrentWriteRequest');
|
||||
const kCurrentShutdownRequest = Symbol('kCurrentShutdownRequest');
|
||||
@ -263,6 +264,14 @@ class JSStreamSocket extends Socket {
|
||||
cb();
|
||||
});
|
||||
}
|
||||
|
||||
get [kSession]() {
|
||||
return this.stream[kSession];
|
||||
}
|
||||
|
||||
set [kSession](session) {
|
||||
this.stream[kSession] = session;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = JSStreamSocket;
|
||||
|
48
test/parallel/test-http2-perform-server-handshake.js
Normal file
48
test/parallel/test-http2-perform-server-handshake.js
Normal file
@ -0,0 +1,48 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const http2 = require('http2');
|
||||
const stream = require('stream');
|
||||
const makeDuplexPair = require('../common/duplexpair');
|
||||
|
||||
// Basic test
|
||||
{
|
||||
const { clientSide, serverSide } = makeDuplexPair();
|
||||
|
||||
const client = http2.connect('http://example.com', {
|
||||
createConnection: () => clientSide,
|
||||
});
|
||||
|
||||
const session = http2.performServerHandshake(serverSide);
|
||||
|
||||
session.on('stream', common.mustCall((stream, headers) => {
|
||||
assert.strictEqual(headers[':path'], '/test');
|
||||
stream.respond({
|
||||
':status': 200,
|
||||
});
|
||||
stream.end('hi!');
|
||||
}));
|
||||
|
||||
const req = client.request({ ':path': '/test' });
|
||||
req.on('response', common.mustCall());
|
||||
req.end();
|
||||
}
|
||||
|
||||
// Double bind should fail
|
||||
{
|
||||
const socket = new stream.Duplex({
|
||||
read() {},
|
||||
write() {},
|
||||
});
|
||||
|
||||
http2.performServerHandshake(socket);
|
||||
|
||||
assert.throws(() => {
|
||||
http2.performServerHandshake(socket);
|
||||
}, { code: 'ERR_HTTP2_SOCKET_BOUND' });
|
||||
}
|
Loading…
Reference in New Issue
Block a user