-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add default root property, cleanup plugin
- Loading branch information
1 parent
96f7e43
commit e485856
Showing
11 changed files
with
790 additions
and
683 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
const { createTerminus, HealthCheckError } = require('@godaddy/terminus'); | ||
const debug = require('diagnostics')('gasket:https'); | ||
const create = require('create-servers'); | ||
const one = require('one-time/async'); | ||
const errs = require('errs'); | ||
const { getPortFallback, portInUseError, startProxy, getRawServerConfig } = require('./utils'); | ||
|
||
/** | ||
* Gasket action: startServer | ||
* @param {import('@gasket/core').Gasket} gasket Gasket instance | ||
* @returns {Promise<void>} promise | ||
* @public | ||
*/ | ||
async function startServer(gasket) { | ||
await gasket.isReady; | ||
const { terminus, env, devProxy } = gasket.config; | ||
const { logger } = gasket; | ||
|
||
if (devProxy) { | ||
const opts = await gasket.execWaterfall('devProxy', devProxy); | ||
return startProxy(Object.assign(devProxy, opts), logger); | ||
} | ||
|
||
const serverConfig = await gasket.execWaterfall('serverConfig', getRawServerConfig(gasket)); | ||
const serverOpts = await gasket.execWaterfall('createServers', serverConfig); | ||
const { healthcheck, ...terminusDefaults } = await gasket.execWaterfall( | ||
'terminus', | ||
{ | ||
healthcheck: ['/healthcheck', '/healthcheck.html'], | ||
signals: ['SIGTERM'], | ||
...(terminus || {}) | ||
} | ||
); | ||
|
||
const routes = Array.isArray(healthcheck) ? healthcheck : [healthcheck]; | ||
|
||
// Default port to non-essential port on creation | ||
// create-servers does not support http or https being `null` | ||
if (!serverOpts.http && !serverOpts.https && !serverOpts.http2) { | ||
serverOpts.http = getPortFallback(env); | ||
} | ||
|
||
/** | ||
* Health check request handler | ||
*/ | ||
async function healthCheckRequested() { | ||
await gasket.traceRoot().exec('healthcheck', HealthCheckError); | ||
} | ||
|
||
// | ||
// It's possible that we are creating multiple servers that are going to hook | ||
// into terminus. We want to eliminate the possibility of double lifecycle | ||
// execution so we're going to create a single options object that is going | ||
// to be used for all terminus based instances. | ||
// | ||
// Lifecycles that could potentially be called multiple times are wrapped | ||
// with a `one-time` function to ensure that the callback is only executed | ||
// once. | ||
// | ||
const terminusOpts = { | ||
logger: logger.error.bind(logger), | ||
onSendFailureDuringShutdown: one( | ||
async function onSendFailureDuringShutdown() { | ||
await gasket.exec('onSendFailureDuringShutdown'); | ||
} | ||
), | ||
beforeShutdown: one(async function beforeShutdown() { | ||
await gasket.exec('beforeShutdown'); | ||
}), | ||
onSignal: one(async function onSignal() { | ||
await gasket.exec('onSignal'); | ||
}), | ||
onShutdown: one(async function onShutdown() { | ||
await gasket.exec('onShutdown'); | ||
}), | ||
healthChecks: routes.reduce((acc, cur) => { | ||
acc[cur] = healthCheckRequested; | ||
return acc; | ||
}, {}), | ||
...terminusDefaults | ||
}; | ||
|
||
// eslint-disable-next-line max-statements | ||
create(serverOpts, async function created(errors, servers) { | ||
if (errors) { | ||
let errorMessage; | ||
|
||
if (portInUseError(errors)) { | ||
errorMessage = errs.create({ | ||
message: | ||
'Port is already in use. Please ensure you are not running the same process from another terminal!', | ||
serverOpts | ||
}); | ||
} else { | ||
errorMessage = errs.create({ | ||
message: `Failed to start the web servers: ${errors.message}`, | ||
serverOpts | ||
}); | ||
} | ||
|
||
debug(errorMessage, errors); | ||
logger.error(errorMessage.message); | ||
return; | ||
} | ||
|
||
// Attach terminus before we call the `servers` lifecycle to ensure that | ||
// everything is setup before the lifecycle is executed. | ||
Object.values(servers) | ||
.reduce((acc, cur) => acc.concat(cur), []) | ||
.forEach((server) => createTerminus(server, terminusOpts)); | ||
|
||
await gasket.exec('servers', servers); | ||
const { | ||
http: _http, | ||
https: _https, | ||
http2: _http2, | ||
hostname: _hostname = 'localhost' | ||
} = serverOpts; | ||
|
||
if (_http) { | ||
// @ts-ignore - http may not be an object, but we account for that | ||
let _port = (typeof _http === 'number' ? _http : _http.port) ?? ''; | ||
if (_port) _port = `:${_port}`; | ||
|
||
logger.info(`Server started at http://${_hostname}${_port}/`); | ||
} | ||
|
||
if (_https || _http2) { | ||
// @ts-ignore - http2 may be an array, but we account for that | ||
let _port = (_https ?? _http2).port ?? ''; | ||
if (_port) _port = `:${_port}`; | ||
|
||
logger.info( | ||
`Server started at https://${_hostname}${_port}/` | ||
); | ||
} | ||
}); | ||
} | ||
|
||
module.exports = { | ||
startServer | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/** @type {import('@gasket/core').HookHandler<'configure'>} */ | ||
module.exports = function configure(gasket, config) { | ||
const { root } = config; | ||
|
||
function setRoot(serverConfig) { | ||
if (!serverConfig) return; | ||
if (serverConfig.root) return; | ||
|
||
if (Array.isArray(serverConfig)) { | ||
serverConfig.forEach(item => { | ||
item.root = root; | ||
}); | ||
} else { | ||
serverConfig.root = root; | ||
} | ||
} | ||
|
||
setRoot(config.https); | ||
setRoot(config.http2); | ||
|
||
return config; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const { name, version } = require('../package.json'); | ||
|
||
/** @type {import('@gasket/core').HookHandler<'create'>} */ | ||
module.exports = async function create(gasket, { pkg, gasketConfig }) { | ||
gasketConfig.addPlugin('pluginHttps', name); | ||
pkg.add('dependencies', { | ||
[name]: `^${version}` | ||
}); | ||
}; |
Oops, something went wrong.