1 | /**
|
2 | * Standalone server script which creates an Express server, configures and
|
3 | * binds it according to configuration, and applies the upward-js middleware.
|
4 | */
|
5 |
|
6 | const { resolve } = require('path');
|
7 | const express = require('express');
|
8 | const middleware = require('./middleware');
|
9 | const errorhandler = require('errorhandler');
|
10 | const { version } = require('../package.json');
|
11 | const morgan = require('morgan');
|
12 |
|
13 | /**
|
14 | * Create an upward-js standalone server and optionally bind it to a local
|
15 | * address. Configure logging and debugging middleware depending on standard
|
16 | * detection of environment: `process.env.NODE_ENV` === 'production'.
|
17 | *
|
18 | * ### `createUpwardServer` Configuration Options
|
19 | *
|
20 | * | Property | Type | Default | Description
|
21 | * | -------- | ---- | ------- | -----------
|
22 | * |`upwardPath` | `string` | | Path, relative to the current directory, of a YML file with an UPWARD configuration. **Required**.
|
23 | * |`bindLocal` | `boolean` | `false` | Create and bind an HTTP server before returning.
|
24 | * |`port` | `number` | `0` | Specify the port to be bound. `0` means the first open port.
|
25 | * |`host` | `string` | `0.0.0.0` | Specify the host on which to listen. `0.0.0.0` means all local IPv4 requests.
|
26 | * |`https` | `object` | | To bind an HTTPS server instead of HTTP, pass a valid `{ key, cert }` object here.
|
27 | * |`logUrl` | `boolean` | `false` | Log the bound URL to stdout (mostly used for testing against upward-spec)
|
28 | *
|
29 | * Returns a plain object with the following properties:
|
30 | * an `app` property. This is an Express
|
31 | *
|
32 | *
|
33 | * @param {object} config Configuration object.
|
34 | * @return Promise `{ app, server?, close? }`
|
35 | */
|
36 | async function createUpwardServer({
|
37 | bindLocal = false,
|
38 | port = 0,
|
39 | host = '0.0.0.0',
|
40 | https,
|
41 | logUrl = false,
|
42 | upwardPath,
|
43 | env = process.env,
|
44 | before = () => {}
|
45 | }) {
|
46 | if (!upwardPath) {
|
47 | throw new Error(`upwardPath is required`);
|
48 | }
|
49 | const app = express();
|
50 | before(app);
|
51 | const upward = await middleware(resolve(upwardPath), env);
|
52 |
|
53 | if (env.NODE_ENV === 'production') {
|
54 | app.use(morgan('combined'));
|
55 | app.use(upward);
|
56 | } else {
|
57 | app.use(morgan('dev'));
|
58 | app.use(upward);
|
59 | errorhandler.title = `⚠️ Error in upward-js v${version}`;
|
60 | app.use(errorhandler());
|
61 | }
|
62 |
|
63 | if (bindLocal) {
|
64 | return new Promise((resolve, reject) => {
|
65 | try {
|
66 | const protocol = https ? 'https' : 'http';
|
67 | const server = https
|
68 | ? require('https').createServer(https, app)
|
69 | : require('http').createServer(app);
|
70 |
|
71 | server.listen(port, host);
|
72 |
|
73 | server.on('listening', () => {
|
74 | if (logUrl) {
|
75 | console.log(
|
76 | `${protocol}://${host}:${server.address().port}/`
|
77 | );
|
78 | }
|
79 | resolve({
|
80 | app,
|
81 | server,
|
82 | close() {
|
83 | return new Promise(resolve => {
|
84 | server.on('close', resolve);
|
85 | server.close();
|
86 | });
|
87 | }
|
88 | });
|
89 | });
|
90 | } catch (e) {
|
91 | reject(e);
|
92 | }
|
93 | });
|
94 | }
|
95 | return { app };
|
96 | }
|
97 |
|
98 | module.exports = createUpwardServer;
|