UNPKG

kraken-js

Version:

An express-based Node.js web application bootstrapping module.

133 lines (107 loc) 4.55 kB
/*───────────────────────────────────────────────────────────────────────────*\ │ Copyright 2016 PayPal │ │ │ │hh ,'""`. │ │ / _ _ \ Licensed under the Apache License, Version 2.0 (the "License"); │ │ |(@)(@)| you may not use this file except in compliance with the License. │ │ ) __ ( You may obtain a copy of the License at │ │ /,'))((`.\ │ │(( (( )) )) http://www.apache.org/licenses/LICENSE-2.0 │ │ `\ `)(' /' │ │ │ │ Unless required by applicable law or agreed to in writing, software │ │ distributed under the License is distributed on an "AS IS" BASIS, │ │ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │ │ See the License for the specific language governing permissions and │ │ limitations under the License. │ \*───────────────────────────────────────────────────────────────────────────*/ 'use strict'; var domain = require('domain'); var thing = require('core-util-is'); var States = { CONNECTED: 0, DISCONNECTING: 2 }; function printDeprecation() { if (/krakendev/i.test(process.env.NODE_ENV)) { return; } console.warn( `DEPRECATION WARNING: Due to deprecation of the domain module in node.js, all features in kraken that depend on it have been deprecated as well. This includes kraken's shutdown middleware. This feature will continue to work in kraken 2.x but consider it unsupported and likely to be removed/replaced in future versions of kraken.`); } function onceThunk() { var called = false; return function once(emitter, events, callback) { function call() { if (!called) { called = true; return callback.apply(this, arguments); // jshint ignore:line } } events.forEach(function (event) { emitter.once(event, call); }); }; } module.exports = function (config) { var template, timeout, state, app, server, once, uncaughtException; function close() { state = States.DISCONNECTING; app.emit('shutdown', server, timeout); } config = config || {}; template = config.template; timeout = config.timeout || 10 * 1000; state = States.CONNECTED; uncaughtException = thing.isFunction(config.uncaughtException) && config.uncaughtException; once = onceThunk(); printDeprecation(); return function shutdown(req, res, next) { var headers, d; headers = config.shutdownHeaders || {}; function json() { res.send({message: 'Server is shutting down.'}); } function html() { template ? res.render(template) : json(); } if (state === States.DISCONNECTING) { headers.Connection = headers.Connection || 'close'; res.header(headers); res.status(503); res.format({ json: json, html: html }); return; } if (!app) { // Lazy-bind - only attempt clean shutdown // if we've taken at least one request. app = req.app; server = req.socket.server; once(process, ['SIGTERM', 'SIGINT'], close); } d = domain.create(); d.add(req); d.add(res); d.run(function () { next(); }); d.once('error', function (error) { if (uncaughtException) { uncaughtException(error, req, res, next); return; } console.error(new Date().toUTCString(), 'UNCAUGHT', error.message); console.error(error.stack); next(error); close(); }); }; };