1 |
|
2 |
|
3 | import type {Server as HTTPOnlyServer} from 'http';
|
4 | import type {Server as HTTPSServer} from 'https';
|
5 | import type {Socket} from 'net';
|
6 | import type {FilePath, HTTPSOptions} from '@parcel/types';
|
7 | import type {FileSystem} from '@parcel/fs';
|
8 |
|
9 | import http from 'http';
|
10 |
|
11 | import {createSecureServer} from 'http2';
|
12 | import nullthrows from 'nullthrows';
|
13 | import {getCertificate, generateCertificate} from '../';
|
14 |
|
15 | type CreateHTTPServerOpts = {|
|
16 | https: ?(HTTPSOptions | boolean),
|
17 | inputFS: FileSystem,
|
18 | outputFS: FileSystem,
|
19 | cacheDir: FilePath,
|
20 | listener?: (mixed, mixed) => void,
|
21 | host?: string,
|
22 | |};
|
23 |
|
24 | export type HTTPServer = HTTPOnlyServer | HTTPSServer;
|
25 |
|
26 |
|
27 |
|
28 | export async function createHTTPServer(
|
29 | options: CreateHTTPServerOpts,
|
30 | ): Promise<{|
|
31 | stop: () => Promise<void>,
|
32 | server: HTTPServer,
|
33 | |}> {
|
34 | let server;
|
35 | if (!options.https) {
|
36 | server = http.createServer(options.listener);
|
37 | } else if (options.https === true) {
|
38 | let {cert, key} = await generateCertificate(
|
39 | options.outputFS,
|
40 | options.cacheDir,
|
41 | options.host,
|
42 | );
|
43 |
|
44 | server = createSecureServer(
|
45 | {cert, key, allowHTTP1: true},
|
46 | options.listener,
|
47 | );
|
48 | } else {
|
49 | let {cert, key} = await getCertificate(options.inputFS, options.https);
|
50 |
|
51 | server = createSecureServer(
|
52 | {cert, key, allowHTTP1: true},
|
53 | options.listener,
|
54 | );
|
55 | }
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 | let sockets: Set<Socket> = new Set();
|
62 | server.on('connection', (socket: Socket) => {
|
63 | nullthrows(sockets).add(socket);
|
64 | socket.on('close', () => {
|
65 | nullthrows(sockets).delete(socket);
|
66 | });
|
67 | });
|
68 | return {
|
69 | server,
|
70 | stop() {
|
71 | return new Promise((resolve, reject) => {
|
72 | for (let socket of nullthrows(sockets)) {
|
73 | socket.destroy();
|
74 | }
|
75 | sockets = new Set();
|
76 |
|
77 | server.close(err => {
|
78 | if (err != null) {
|
79 | reject(err);
|
80 | return;
|
81 | }
|
82 |
|
83 | resolve();
|
84 | });
|
85 | });
|
86 | },
|
87 | };
|
88 | }
|