@httptoolkit/httpolyglot 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +33 -1
- package/dist/index.js +40 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +80 -20
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import * as net from 'net';
|
|
3
|
+
import * as tls from 'tls';
|
|
3
4
|
import * as http from 'http';
|
|
4
5
|
import * as https from 'https';
|
|
5
6
|
declare module 'net' {
|
|
@@ -11,10 +12,41 @@ export declare class Server extends net.Server {
|
|
|
11
12
|
private _httpServer;
|
|
12
13
|
private _http2Server;
|
|
13
14
|
private _tlsServer;
|
|
15
|
+
/**
|
|
16
|
+
* Create an Httpolyglot instance with just a request listener to support plain-text
|
|
17
|
+
* HTTP & HTTP/2 on the same port, with incoming TLS connections being closed immediately.
|
|
18
|
+
*/
|
|
14
19
|
constructor(requestListener: http.RequestListener);
|
|
15
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Call with a full TLS configuration to create a TLS+HTTP+HTTP/2 server, which can
|
|
22
|
+
* support all protocols on the same port.
|
|
23
|
+
*/
|
|
24
|
+
constructor(config: https.ServerOptions, requestListener: http.RequestListener);
|
|
25
|
+
/**
|
|
26
|
+
* Pass an existing TLS server, instead of TLS configuration, to create a TLS+HTTP+HTTP/2
|
|
27
|
+
* server. All incoming TLS requests will be emitted as 'connection' events on the given
|
|
28
|
+
* TLS server, and all 'secureConnection' events coming from the TLS server will be
|
|
29
|
+
* handled according to the connection type detected on that socket.
|
|
30
|
+
*/
|
|
31
|
+
constructor(tlsServer: tls.Server, requestListener: http.RequestListener);
|
|
16
32
|
private connectionListener;
|
|
33
|
+
private tlsListener;
|
|
17
34
|
private http2Listener;
|
|
18
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Create an Httpolyglot instance with just a request listener to support plain-text
|
|
38
|
+
* HTTP & HTTP/2 on the same port, with incoming TLS connections being closed immediately.
|
|
39
|
+
*/
|
|
19
40
|
export declare function createServer(requestListener: http.RequestListener): Server;
|
|
41
|
+
/**
|
|
42
|
+
* Create an instance with a full TLS configuration to create a TLS+HTTP+HTTP/2 server, which can
|
|
43
|
+
* support all protocols on the same port.
|
|
44
|
+
*/
|
|
20
45
|
export declare function createServer(tlsConfig: https.ServerOptions, requestListener: http.RequestListener): Server;
|
|
46
|
+
/**
|
|
47
|
+
* Create an instance around an existing TLS server, instead of TLS configuration, to create a
|
|
48
|
+
* TLS+HTTP+HTTP/2 server with custom TLS handling. All incoming TLS requests will be emitted as
|
|
49
|
+
* 'connection' events on the given TLS server, and all 'secureConnection' events coming from the
|
|
50
|
+
* TLS server will be handled according to the connection type detected on that socket.
|
|
51
|
+
*/
|
|
52
|
+
export declare function createServer(tlsServer: tls.Server, requestListener: http.RequestListener): Server;
|
package/dist/index.js
CHANGED
|
@@ -10,19 +10,25 @@ function onError(err) { }
|
|
|
10
10
|
const TLS_HANDSHAKE_BYTE = 0x16; // SSLv3+ or TLS handshake
|
|
11
11
|
const HTTP2_PREFACE = 'PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n';
|
|
12
12
|
const HTTP2_PREFACE_BUFFER = Buffer.from(HTTP2_PREFACE);
|
|
13
|
+
const NODE_MAJOR_VERSION = parseInt(process.version.slice(1).split('.')[0], 10);
|
|
13
14
|
class Server extends net.Server {
|
|
14
|
-
constructor(
|
|
15
|
+
constructor(configOrServerOrListener, listener) {
|
|
15
16
|
// We just act as a plain TCP server, accepting and examing
|
|
16
17
|
// each connection, then passing it to the right subserver.
|
|
17
18
|
super((socket) => this.connectionListener(socket));
|
|
18
19
|
let tlsConfig;
|
|
20
|
+
let tlsServer;
|
|
19
21
|
let requestListener;
|
|
20
|
-
if (typeof
|
|
21
|
-
requestListener =
|
|
22
|
+
if (typeof configOrServerOrListener === 'function') {
|
|
23
|
+
requestListener = configOrServerOrListener;
|
|
22
24
|
tlsConfig = undefined;
|
|
23
25
|
}
|
|
26
|
+
else if (configOrServerOrListener instanceof tls.Server) {
|
|
27
|
+
tlsServer = configOrServerOrListener;
|
|
28
|
+
requestListener = listener;
|
|
29
|
+
}
|
|
24
30
|
else {
|
|
25
|
-
tlsConfig =
|
|
31
|
+
tlsConfig = configOrServerOrListener;
|
|
26
32
|
requestListener = listener;
|
|
27
33
|
}
|
|
28
34
|
// We bind the request listener, so 'this' always refers to us, not each subserver.
|
|
@@ -31,17 +37,16 @@ class Server extends net.Server {
|
|
|
31
37
|
// Create subservers for each supported protocol:
|
|
32
38
|
this._httpServer = new http.Server(boundListener);
|
|
33
39
|
this._http2Server = http2.createServer({}, boundListener);
|
|
34
|
-
if (
|
|
40
|
+
if (tlsServer) {
|
|
41
|
+
// If we've been given a preconfigured TLS server, we use that directly, and
|
|
42
|
+
// subscribe to connections there
|
|
43
|
+
this._tlsServer = tlsServer;
|
|
44
|
+
this._tlsServer.on('secureConnection', this.tlsListener.bind(this));
|
|
45
|
+
}
|
|
46
|
+
else if (typeof tlsConfig === 'object') {
|
|
35
47
|
// If we have TLS config, create a TLS server, which will pass sockets to
|
|
36
48
|
// the relevant subserver once the TLS connection is set up.
|
|
37
|
-
this._tlsServer = new tls.Server(tlsConfig, (
|
|
38
|
-
if (tlsSocket.alpnProtocol === false || tlsSocket.alpnProtocol === 'http/1.1') {
|
|
39
|
-
this._httpServer.emit('connection', tlsSocket);
|
|
40
|
-
}
|
|
41
|
-
else {
|
|
42
|
-
this._http2Server.emit('connection', tlsSocket);
|
|
43
|
-
}
|
|
44
|
-
});
|
|
49
|
+
this._tlsServer = new tls.Server(tlsConfig, this.tlsListener.bind(this));
|
|
45
50
|
}
|
|
46
51
|
else {
|
|
47
52
|
// Fake server that rejects all connections:
|
|
@@ -99,6 +104,14 @@ class Server extends net.Server {
|
|
|
99
104
|
}
|
|
100
105
|
}
|
|
101
106
|
}
|
|
107
|
+
tlsListener(tlsSocket) {
|
|
108
|
+
if (tlsSocket.alpnProtocol === false || tlsSocket.alpnProtocol === 'http/1.1') {
|
|
109
|
+
this._httpServer.emit('connection', tlsSocket);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
this._http2Server.emit('connection', tlsSocket);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
102
115
|
http2Listener(socket, pastData) {
|
|
103
116
|
const h1Server = this._httpServer;
|
|
104
117
|
const h2Server = this._http2Server;
|
|
@@ -108,11 +121,18 @@ class Server extends net.Server {
|
|
|
108
121
|
socket.unshift(data);
|
|
109
122
|
if (data.slice(0, HTTP2_PREFACE_BUFFER.length).equals(HTTP2_PREFACE_BUFFER)) {
|
|
110
123
|
// We have a full match for the preface - it's definitely HTTP/2.
|
|
111
|
-
// For HTTP/2 we hit issues when passing non-socket streams (like
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
124
|
+
// For HTTP/2 we hit issues when passing non-socket streams (like H2 streams for proxying H2-over-H2).
|
|
125
|
+
if (NODE_MAJOR_VERSION <= 12) {
|
|
126
|
+
// For Node 12 and older, we need a (later deprecated) stream wrapper:
|
|
127
|
+
const StreamWrapper = require('_stream_wrap');
|
|
128
|
+
socket = new StreamWrapper(socket);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
// For newer node, we can fix this with a quick patch here:
|
|
132
|
+
const socketWithInternals = socket;
|
|
133
|
+
if (socketWithInternals._handle) {
|
|
134
|
+
socketWithInternals._handle.isStreamBase = false;
|
|
135
|
+
}
|
|
116
136
|
}
|
|
117
137
|
h2Server.emit('connection', socket);
|
|
118
138
|
return;
|
|
@@ -137,8 +157,8 @@ class Server extends net.Server {
|
|
|
137
157
|
}
|
|
138
158
|
}
|
|
139
159
|
exports.Server = Server;
|
|
140
|
-
function createServer(
|
|
141
|
-
return new Server(
|
|
160
|
+
function createServer(configOrServerOrListener, listener) {
|
|
161
|
+
return new Server(configOrServerOrListener, listener);
|
|
142
162
|
}
|
|
143
163
|
exports.createServer = createServer;
|
|
144
164
|
;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2BAA2B;AAC3B,2BAA2B;AAC3B,6BAA6B;AAE7B,+BAA+B;AAE/B,mCAAsC;AAQtC,SAAS,OAAO,CAAC,GAAQ,IAAG,CAAC;AAE7B,MAAM,kBAAkB,GAAG,IAAI,CAAC,CAAC,0BAA0B;AAC3D,MAAM,aAAa,GAAG,kCAAkC,CAAC;AACzD,MAAM,oBAAoB,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -18,6 +18,8 @@ const TLS_HANDSHAKE_BYTE = 0x16; // SSLv3+ or TLS handshake
|
|
|
18
18
|
const HTTP2_PREFACE = 'PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n';
|
|
19
19
|
const HTTP2_PREFACE_BUFFER = Buffer.from(HTTP2_PREFACE);
|
|
20
20
|
|
|
21
|
+
const NODE_MAJOR_VERSION = parseInt(process.version.slice(1).split('.')[0], 10);
|
|
22
|
+
|
|
21
23
|
type Http2Listener = (request: http2.Http2ServerRequest, response: http2.Http2ServerResponse) => void;
|
|
22
24
|
|
|
23
25
|
export class Server extends net.Server {
|
|
@@ -26,21 +28,46 @@ export class Server extends net.Server {
|
|
|
26
28
|
private _http2Server: http2.Http2Server;
|
|
27
29
|
private _tlsServer: EventEmitter;
|
|
28
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Create an Httpolyglot instance with just a request listener to support plain-text
|
|
33
|
+
* HTTP & HTTP/2 on the same port, with incoming TLS connections being closed immediately.
|
|
34
|
+
*/
|
|
29
35
|
constructor(requestListener: http.RequestListener);
|
|
30
|
-
|
|
31
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Call with a full TLS configuration to create a TLS+HTTP+HTTP/2 server, which can
|
|
38
|
+
* support all protocols on the same port.
|
|
39
|
+
*/
|
|
40
|
+
constructor(config: https.ServerOptions, requestListener: http.RequestListener);
|
|
41
|
+
/**
|
|
42
|
+
* Pass an existing TLS server, instead of TLS configuration, to create a TLS+HTTP+HTTP/2
|
|
43
|
+
* server. All incoming TLS requests will be emitted as 'connection' events on the given
|
|
44
|
+
* TLS server, and all 'secureConnection' events coming from the TLS server will be
|
|
45
|
+
* handled according to the connection type detected on that socket.
|
|
46
|
+
*/
|
|
47
|
+
constructor(tlsServer: tls.Server, requestListener: http.RequestListener);
|
|
48
|
+
constructor(
|
|
49
|
+
configOrServerOrListener:
|
|
50
|
+
| https.ServerOptions
|
|
51
|
+
| tls.Server
|
|
52
|
+
| http.RequestListener,
|
|
53
|
+
listener?: http.RequestListener
|
|
54
|
+
) {
|
|
32
55
|
// We just act as a plain TCP server, accepting and examing
|
|
33
56
|
// each connection, then passing it to the right subserver.
|
|
34
57
|
super((socket) => this.connectionListener(socket));
|
|
35
58
|
|
|
36
59
|
let tlsConfig: https.ServerOptions | undefined;
|
|
60
|
+
let tlsServer: tls.Server | undefined;
|
|
37
61
|
let requestListener: http.RequestListener;
|
|
38
62
|
|
|
39
|
-
if (typeof
|
|
40
|
-
requestListener =
|
|
63
|
+
if (typeof configOrServerOrListener === 'function') {
|
|
64
|
+
requestListener = configOrServerOrListener;
|
|
41
65
|
tlsConfig = undefined;
|
|
66
|
+
} else if (configOrServerOrListener instanceof tls.Server) {
|
|
67
|
+
tlsServer = configOrServerOrListener;
|
|
68
|
+
requestListener = listener!;
|
|
42
69
|
} else {
|
|
43
|
-
tlsConfig =
|
|
70
|
+
tlsConfig = configOrServerOrListener;
|
|
44
71
|
requestListener = listener!;
|
|
45
72
|
}
|
|
46
73
|
|
|
@@ -52,16 +79,15 @@ export class Server extends net.Server {
|
|
|
52
79
|
this._httpServer = new http.Server(boundListener);
|
|
53
80
|
this._http2Server = http2.createServer({}, boundListener as any as Http2Listener);
|
|
54
81
|
|
|
55
|
-
if (
|
|
82
|
+
if (tlsServer) {
|
|
83
|
+
// If we've been given a preconfigured TLS server, we use that directly, and
|
|
84
|
+
// subscribe to connections there
|
|
85
|
+
this._tlsServer = tlsServer;
|
|
86
|
+
this._tlsServer.on('secureConnection', this.tlsListener.bind(this));
|
|
87
|
+
} else if (typeof tlsConfig === 'object') {
|
|
56
88
|
// If we have TLS config, create a TLS server, which will pass sockets to
|
|
57
89
|
// the relevant subserver once the TLS connection is set up.
|
|
58
|
-
this._tlsServer = new tls.Server(tlsConfig, (
|
|
59
|
-
if (tlsSocket.alpnProtocol === false || tlsSocket.alpnProtocol === 'http/1.1') {
|
|
60
|
-
this._httpServer.emit('connection', tlsSocket);
|
|
61
|
-
} else {
|
|
62
|
-
this._http2Server.emit('connection', tlsSocket);
|
|
63
|
-
}
|
|
64
|
-
});
|
|
90
|
+
this._tlsServer = new tls.Server(tlsConfig, this.tlsListener.bind(this));
|
|
65
91
|
} else {
|
|
66
92
|
// Fake server that rejects all connections:
|
|
67
93
|
this._tlsServer = new EventEmitter();
|
|
@@ -124,6 +150,14 @@ export class Server extends net.Server {
|
|
|
124
150
|
}
|
|
125
151
|
}
|
|
126
152
|
|
|
153
|
+
private tlsListener(tlsSocket: tls.TLSSocket) {
|
|
154
|
+
if (tlsSocket.alpnProtocol === false || tlsSocket.alpnProtocol === 'http/1.1') {
|
|
155
|
+
this._httpServer.emit('connection', tlsSocket);
|
|
156
|
+
} else {
|
|
157
|
+
this._http2Server.emit('connection', tlsSocket);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
127
161
|
private http2Listener(socket: net.Socket, pastData?: Buffer) {
|
|
128
162
|
const h1Server = this._httpServer;
|
|
129
163
|
const h2Server = this._http2Server;
|
|
@@ -136,11 +170,17 @@ export class Server extends net.Server {
|
|
|
136
170
|
if (data.slice(0, HTTP2_PREFACE_BUFFER.length).equals(HTTP2_PREFACE_BUFFER)) {
|
|
137
171
|
// We have a full match for the preface - it's definitely HTTP/2.
|
|
138
172
|
|
|
139
|
-
// For HTTP/2 we hit issues when passing non-socket streams (like
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
173
|
+
// For HTTP/2 we hit issues when passing non-socket streams (like H2 streams for proxying H2-over-H2).
|
|
174
|
+
if (NODE_MAJOR_VERSION <= 12) {
|
|
175
|
+
// For Node 12 and older, we need a (later deprecated) stream wrapper:
|
|
176
|
+
const StreamWrapper = require('_stream_wrap');
|
|
177
|
+
socket = new StreamWrapper(socket);
|
|
178
|
+
} else {
|
|
179
|
+
// For newer node, we can fix this with a quick patch here:
|
|
180
|
+
const socketWithInternals = socket as { _handle?: { isStreamBase?: boolean } };
|
|
181
|
+
if (socketWithInternals._handle) {
|
|
182
|
+
socketWithInternals._handle.isStreamBase = false;
|
|
183
|
+
}
|
|
144
184
|
}
|
|
145
185
|
|
|
146
186
|
h2Server.emit('connection', socket);
|
|
@@ -165,8 +205,28 @@ export class Server extends net.Server {
|
|
|
165
205
|
}
|
|
166
206
|
}
|
|
167
207
|
|
|
208
|
+
/**
|
|
209
|
+
* Create an Httpolyglot instance with just a request listener to support plain-text
|
|
210
|
+
* HTTP & HTTP/2 on the same port, with incoming TLS connections being closed immediately.
|
|
211
|
+
*/
|
|
168
212
|
export function createServer(requestListener: http.RequestListener): Server;
|
|
213
|
+
/**
|
|
214
|
+
* Create an instance with a full TLS configuration to create a TLS+HTTP+HTTP/2 server, which can
|
|
215
|
+
* support all protocols on the same port.
|
|
216
|
+
*/
|
|
169
217
|
export function createServer(tlsConfig: https.ServerOptions, requestListener: http.RequestListener): Server;
|
|
170
|
-
|
|
171
|
-
|
|
218
|
+
/**
|
|
219
|
+
* Create an instance around an existing TLS server, instead of TLS configuration, to create a
|
|
220
|
+
* TLS+HTTP+HTTP/2 server with custom TLS handling. All incoming TLS requests will be emitted as
|
|
221
|
+
* 'connection' events on the given TLS server, and all 'secureConnection' events coming from the
|
|
222
|
+
* TLS server will be handled according to the connection type detected on that socket.
|
|
223
|
+
*/
|
|
224
|
+
export function createServer(tlsServer: tls.Server, requestListener: http.RequestListener): Server;
|
|
225
|
+
export function createServer(configOrServerOrListener:
|
|
226
|
+
| https.ServerOptions
|
|
227
|
+
| http.RequestListener
|
|
228
|
+
| tls.Server,
|
|
229
|
+
listener?: http.RequestListener
|
|
230
|
+
) {
|
|
231
|
+
return new Server(configOrServerOrListener as any, listener as any);
|
|
172
232
|
};
|