UNPKG

2.95 kBPlain TextView Raw
1// Copyright IBM Corp. and LoopBack contributors 2018,2020. All Rights Reserved.
2// Node module: @loopback/testlab
3// This file is licensed under the MIT License.
4// License text available at https://opensource.org/licenses/MIT
5
6import assert from 'assert';
7import {readFileSync} from 'fs';
8import {ServerOptions as HttpsServerOptions} from 'https';
9import {ListenOptions} from 'net';
10import path from 'path';
11
12const FIXTURES = path.resolve(__dirname, '../fixtures');
13const DUMMY_TLS_CONFIG = {
14 key: readFileSync(path.join(FIXTURES, 'key.pem')),
15 cert: readFileSync(path.join(FIXTURES, 'cert.pem')),
16};
17
18export interface HttpOptions extends ListenOptions {
19 protocol?: 'http';
20}
21
22export interface HttpsOptions extends ListenOptions, HttpsServerOptions {
23 protocol: 'https';
24}
25
26/**
27 * An object that requires host and port properties
28 */
29export interface HostPort {
30 host: string;
31 port: number;
32}
33
34/**
35 * Assertion type guard for TypeScript to ensure `host` and `port` are set
36 * @param config - Host/port configuration
37 */
38function assertHostPort(config: Partial<HostPort>): asserts config is HostPort {
39 assert(config.host != null, 'host is not set');
40 assert(config.port != null, 'port is not set');
41}
42
43/**
44 * Create an HTTP-server configuration that works well in test environments.
45 * - Ask the operating system to assign a free (ephemeral) port.
46 * - Use IPv4 localhost `127.0.0.1` to avoid known IPv6 issues in Docker-based
47 * environments like Travis-CI.
48 * - Provide default TLS key & cert when `protocol` is set to `https`.
49 *
50 * @param customConfig - Additional configuration options to apply.
51 */
52export function givenHttpServerConfig<T extends HttpOptions | HttpsOptions>(
53 customConfig?: T,
54): HostPort & T {
55 const defaults: HostPort = {host: '127.0.0.1', port: 0};
56
57 if (isHttpsConfig(customConfig)) {
58 const config: T = {...customConfig};
59 if (config.host == null) config.host = defaults.host;
60 if (config.port == null) config.port = defaults.port;
61 setupTlsConfig(config);
62 assertHostPort(config);
63 return config;
64 }
65
66 assertHttpConfig(customConfig);
67 const config: T = {...customConfig};
68 if (config.host == null) config.host = defaults.host;
69 if (config.port == null) config.port = defaults.port;
70 assertHostPort(config);
71 return config;
72}
73
74function setupTlsConfig(config: HttpsServerOptions) {
75 if ('key' in config && 'cert' in config) return;
76 if ('pfx' in config) return;
77 Object.assign(config, DUMMY_TLS_CONFIG);
78}
79
80/**
81 * Type guard to check if the parameter is `HttpsOptions`
82 */
83function isHttpsConfig(
84 config?: HttpOptions | HttpsOptions,
85): config is HttpsOptions {
86 return config?.protocol === 'https';
87}
88
89/**
90 * Type guard to assert the parameter is `HttpOptions`
91 * @param config - Http config
92 */
93function assertHttpConfig(
94 config?: HttpOptions | HttpsOptions,
95): asserts config is HttpOptions {
96 assert(config?.protocol == null || config?.protocol === 'http');
97}