├── .editorconfig
├── .eslintrc
├── .github
├── FUNDING.yml
└── workflows
│ └── codeql.yml
├── .gitignore
├── LICENSE
├── README.md
├── docs
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE.md
└── PULL_REQUEST_TEMPLATE.md
├── examples
├── README.md
├── express-advanced-server.js
├── express-noexit-server.js
├── express-simple-server.js
├── fastity-simple-server.js
├── http-simple-server.js
├── http2-simple-server.js
└── koa-simple-server.js
├── lib
├── index.d.ts
└── index.js
└── package.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # For more information about the properties used in
2 | # this file, please see the EditorConfig documentation:
3 | # http://editorconfig.org/
4 |
5 | # top-most EditorConfig file
6 | root = true
7 |
8 | [*]
9 | charset = utf-8
10 | end_of_line = lf
11 | indent_style = space
12 | indent_size = 2
13 | insert_final_newline = true
14 | trim_trailing_whitespace = true
15 |
16 | [*.md]
17 | trim_trailing_whitespace = true
18 |
19 | [{.travis.yml,package.json}]
20 | # The indent size used in the `package.json` file cannot be changed
21 | # https://github.com/npm/npm/pull/3180#issuecomment-16336516
22 | indent_style = space
23 | indent_size = 2
24 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": false,
4 | "commonjs": true,
5 | "es2021": true,
6 | "node": true
7 | },
8 | "extends": "eslint:recommended",
9 | "parserOptions": {
10 | "ecmaVersion": 12
11 | },
12 | "rules": {
13 | "semi": [
14 | "error",
15 | "always"
16 | ],
17 | "eqeqeq": "off",
18 | "curly": "error",
19 | "quotes": [
20 | "error",
21 | "single"
22 | ]
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: 'sebhildebrandt'
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: #['link']
13 |
--------------------------------------------------------------------------------
/.github/workflows/codeql.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL"
13 |
14 | on:
15 | push:
16 | branches: [ "master" ]
17 | pull_request:
18 | # The branches below must be a subset of the branches above
19 | branches: [ "master" ]
20 | schedule:
21 | - cron: '43 7 * * 6'
22 |
23 | jobs:
24 | analyze:
25 | name: Analyze
26 | runs-on: ubuntu-latest
27 | permissions:
28 | actions: read
29 | contents: read
30 | security-events: write
31 |
32 | strategy:
33 | fail-fast: false
34 | matrix:
35 | language: [ 'javascript' ]
36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
38 |
39 | steps:
40 | - name: Checkout repository
41 | uses: actions/checkout@v3
42 |
43 | # Initializes the CodeQL tools for scanning.
44 | - name: Initialize CodeQL
45 | uses: github/codeql-action/init@v2
46 | with:
47 | languages: ${{ matrix.language }}
48 | # If you wish to specify custom queries, you can do so here or in a config file.
49 | # By default, queries listed here will override any specified in a config file.
50 | # Prefix the list here with "+" to use these queries and those in the config file.
51 |
52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
53 | # queries: security-extended,security-and-quality
54 |
55 |
56 | # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
57 | # If this step fails, then you should remove it and run the build manually (see below)
58 | - name: Autobuild
59 | uses: github/codeql-action/autobuild@v2
60 |
61 | # ℹ️ Command-line programs to run using the OS shell.
62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
63 |
64 | # If the Autobuild fails above, remove it and uncomment the following three lines.
65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
66 |
67 | # - run: |
68 | # echo "Run, Build Application using script"
69 | # ./location_of_script_within_repo/buildscript.sh
70 |
71 | - name: Perform CodeQL Analysis
72 | uses: github/codeql-action/analyze@v2
73 | with:
74 | category: "/language:${{matrix.language}}"
75 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 |
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 |
16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17 | .grunt
18 |
19 | # node-waf configuration
20 | .lock-wscript
21 |
22 | # Compiled binary addons (http://nodejs.org/api/addons.html)
23 | build/Release
24 |
25 | # MacOS
26 | .DS_Store
27 | .Spotlight-V100
28 | .Trashes
29 | Icon?
30 | ._*
31 |
32 | # Windows
33 | Thumbs.db
34 | ehthumbs.db
35 | Desktop.ini
36 |
37 | # Linux
38 | .directory
39 | *~
40 |
41 | # NPM
42 | node_modules
43 | .nodemonignore
44 | npm-debug.log
45 | npm*
46 | *.gz
47 | examples/package*
48 |
49 | # Other
50 | *_conflict-
51 | .notes.txt
52 | .idea
53 | *.ipr
54 | *.iws
55 | *.sublime-project
56 | *.sublime-workspace
57 | .*.swp
58 | .svn
59 | .hg
60 | CVS
61 | .eslintrc.json
62 | package-lock.json
63 | yarn.lock
64 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015-2025 Sebastian Hildebrandt
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # http-graceful-shutdown
2 |
3 | ```
4 | _ _ _ __ _ _ _ _
5 | | |_| |_| |_ _ __ ___ __ _ _ _ __ _ __ ___ / _|_ _| |___ __| |_ _ _| |_ __| |_____ __ ___ _
6 | | ' \ _| _| '_ \___/ _` | '_/ _` / _/ -_) _| || | |___(_-< ' \ || | _/ _` / _ \ V V / ' \
7 | |_||_\__|\__| .__/ \__, |_| \__,_\__\___|_| \_,_|_| /__/_||_\_,_|\__\__,_\___/\_/\_/|_||_|
8 | |_| |___/
9 | ```
10 |
11 | Gracefully shuts down [node.js][nodejs-url] http server. More than 10 Mio
12 | downloads overall.
13 |
14 | [![NPM Version][npm-image]][npm-url]
15 | [![NPM Downloads][downloads-image]][downloads-url]
16 | [![Git Issues][issues-img]][issues-url]
17 | [![Closed Issues][closed-issues-img]][closed-issues-url]
18 | [![deps status][dependencies-img]][dependencies-url]
19 | [![Caretaker][caretaker-image]][caretaker-url]
20 | [![MIT license][license-img]][license-url]
21 |
22 | **Version 3.0** just released. This version is fully backwards compatible to
23 | version 2.x but adds much better handling under the hood. More that 10 Mio
24 | downloads.
25 |
26 | - can be used with [express][express-url], [koa][koa-url],
27 | [fastify][fastify-url], native node [http][http-url], [http2][http2-url] ...
28 | see examples
29 | - simple to use
30 | - configurable to your needs
31 | - add your own cleanup function
32 |
33 | ### Features
34 |
35 | `http-graceful-shutdown` manages a secure and save shutdown of your http server
36 | application:
37 |
38 | - tracks all connections
39 | - stops the server from accepting new connections on shutdown
40 | - graceful communication to all connected clients of server intention to shut
41 | down
42 | - immediately destroys all sockets without an attached HTTP request
43 | - properly handles all HTTP and HTTPS connections
44 | - possibility to define cleanup functions (e.g. closing DB connections)
45 | - preShutdown function if you need to have all HTTP sockets available and
46 | untouched
47 | - choose between shutting down by function call or triggered by SIGINT, SIGTERM,
48 | ...
49 | - choose between final forceful process termination node.js (process.exit) or
50 | clearing event loop (options).
51 |
52 | ## Quick Start
53 |
54 | ### Installation
55 |
56 | ```bash
57 | $ npm install http-graceful-shutdown
58 | ```
59 |
60 | ### Basic Usage
61 |
62 | ```js
63 | const gracefulShutdown = require('http-graceful-shutdown');
64 | ...
65 | // app: can be http, https, express, koa, fastity, ...
66 | server = app.listen(...);
67 | ...
68 |
69 | // this enables the graceful shutdown
70 | gracefulShutdown(server);
71 | ```
72 |
73 | ## Explanation
74 |
75 | ### Functionality
76 |
77 | ```
78 | PARENT Process (e.g. nodemon, shell, kubernetes, ...)
79 | ─────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────
80 | │ Signal (SIGINT, SIGTERM, ...)
81 | │
82 | │
83 | (1) (2) v NODE SERVER (HTTP, Express, koa, fastity, ...)
84 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇
85 | │ │ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ │ <─ shutdown procedure
86 | │ │ shutdown initiated │ │ │
87 | │ │ │ │ │
88 | │ │ │ │ (8) shutdown function (9) finally fn │
89 | │ │ ▄▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄ │ │ ▄▄ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄ │
90 | │ └ (3) (4) close │ └ (7) destroy │
91 | │ preShutdown idle sockets │ remaining sockets │
92 | │ │ │ (10)
93 | serve │ serving req. (open connection) │ (5) └ SERVER terminated
94 | ▄▄▄│ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄┤ ^ blocked
95 | ^ │ ^ last request before │ │
96 | │ │ │ receiving shutdown signal │ │
97 | │ │ │ │ │
98 | │ │ │ │ │
99 | │ │ │ │ │
100 | │ │ │ Long request │ │
101 | Request │ V Resp │ V Resp. │
102 | │ │ │ CLIENT
103 | ────────┴─────────┴─────────────────────────────────────────────────┴─────────────────────────────────────────────────────────
104 | ```
105 |
106 | 1. usually, your NODE http server (the black bar in the middle) replies to
107 | client requests and sends responses
108 | 2. if your server receives a termination signal (e.g. SIGINT - Ctrl-C) from its
109 | parent, http-graceful-shutdown starts the shutdown procedure
110 | 3. first, http-graceful-shutdown will run the "preShutdown" (async) function.
111 | Place your own function here (passed to the options object), if you need to
112 | have all HTTP sockets available and untouched.
113 | 4. then all empty connections are closed and destroyed and
114 | 5. http-graceful-shutdown will block any new requests
115 | 6. if possible, http-graceful-shutdown communicates to the clients that the
116 | server is about to close (connection close header)
117 | 7. http-graceful-shutdown now tries to wait till all sockets are finished, then
118 | destroys the all remaining sockets
119 | 8. now it is time to run the "onShutdown" (async) function (if such a function
120 | is passed to the options object)
121 | 9. as soon as this onShutdown function has ended, the "finally" (sync) function
122 | is executed (if passed to the options)
123 | 10. now the event loop is cleared up OR process.exit() is triggered (can be
124 | defined in the options) and the server process ends.
125 |
126 | ## Options
127 |
128 | | option | default | Comments |
129 | | ----------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------- |
130 | | timeout | 30000 | timeout till forced shutdown (in milliseconds) |
131 | | signals | 'SIGINT SIGTERM' | define the signals, that should be handled (separated by SPACE) |
132 | | development | false | if set to true, no graceful shutdown is proceeded to speed up dev-process |
133 | | preShutdown | - | not time-consuming callback function. Needs to return a promise.
Here, all HTTP sockets are still available and untouched |
134 | | onShutdown | - | not time-consuming callback function. Needs to return a promise. |
135 | | forceExit | true | force process.exit - otherwise just let event loop clear |
136 | | finally | - | small, not time-consuming function, that will
be handled at the end of the shutdown (not in dev-mode) |
137 |
138 | ### Option Explanation
139 |
140 | - **timeout:** You can define the maximum time that the shutdown process may
141 | take (timeout option). If after this time, connections are still open or the
142 | shutdown process is still running, then the remaining connections will be
143 | forcibly closed and the server process is terminated.
144 | - **signals** Here you can define which signals can trigger the shutdown process
145 | (SIGINT, SIGTERM, SIGKILL, SIGHUP, SIGUSR2, ...)
146 | - **development** If true, the shutdown process is much shorter, because it just
147 | terminates the server, ignoring open connections, shutdown function, finally
148 | function ...
149 | - **preShutdown** Place your own (not time-consuming) callback function here, if
150 | you need to have all HTTP sockets available and untouched during cleanup.
151 | Needs to return a promise. (async). If you add an input parameter to your
152 | cleanup function (optional), the SIGNAL type that caused the shutdown is
153 | passed to your cleanup function. See example.
154 | - **onShutdown** place your (not time-consuming) callback function, that will
155 | handle your additional cleanup things (e.g. close DB connections). Needs to
156 | return a promise. (async). If you add an input parameter to your cleanup
157 | function (optional), the SIGNAL type that caused the shutdown is passed to
158 | your cleanup function. See example.
159 | - **finally** here you can place a small (not time-consuming) function, that
160 | will be handled at the end of the shutdown e.g. for logging of shutdown.
161 | (sync)
162 | - **forceExit** force process.exit() at the end of the shutdown process,
163 | otherwise just let event loop clear
164 |
165 | ### Advanced Options Example
166 |
167 | You can pass an options-object to specify your specific options for the graceful
168 | shutdown
169 |
170 | The following example uses all possible options:
171 |
172 | ```js
173 | const gracefulShutdown = require('http-graceful-shutdown');
174 | ...
175 | // app: can be http, https, express, koa, fastity, ...
176 | server = app.listen(...);
177 | ...
178 |
179 | // your personal cleanup function
180 | // - must return a promise
181 | // - the input parameter is optional (only needed if you want to
182 | // access the signal type inside this function)
183 | // - this function here in this example takes one second to complete
184 | function shutdownFunction(signal) {
185 | return new Promise((resolve) => {
186 | console.log('... called signal: ' + signal);
187 | console.log('... in cleanup')
188 | setTimeout(function() {
189 | console.log('... cleanup finished');
190 | resolve();
191 | }, 1000)
192 | });
193 | }
194 |
195 | // finally function
196 | // -- sync function
197 | // -- should be very short (not time consuming)
198 | function finalFunction() {
199 | console.log('Server gracefulls shutted down.....')
200 | }
201 |
202 | // this enables the graceful shutdown with advanced options
203 | gracefulShutdown(server,
204 | {
205 | signals: 'SIGINT SIGTERM',
206 | timeout: 10000, // timeout: 10 secs
207 | development: false, // not in dev mode
208 | forceExit: true, // triggers process.exit() at the end of shutdown process
209 | preShutdown: preShutdownFunction, // needed operation before httpConnections are shutted down
210 | onShutdown: shutdownFunction, // shutdown function (async) - e.g. for cleanup DB, ...
211 | finally: finalFunction // finally function (sync) - e.g. for logging
212 | }
213 | );
214 | ```
215 |
216 | ### Trigger shutdown manually
217 |
218 | You can now trigger gracefulShutdown programatically (e.g. for tests) like so:
219 |
220 | ```js
221 | let shutdown
222 | beforeAll(() => {
223 | shutdown = gracefulShutdown(...)
224 | })
225 |
226 | afterAll(async () => {
227 | await shutdown()
228 | })
229 | ```
230 |
231 | ### Do not force process.exit()
232 |
233 | With the `forceExit` option, you can define how your node server process ends:
234 | when setting `forceExit` to `false`, you just let the event loop clear and then
235 | the proccess ends automatically:
236 |
237 | ```js
238 | const gracefulShutdown = require('http-graceful-shutdown');
239 | ...
240 | // app: can be http, https, express, koa, fastity, ...
241 | server = app.listen(...);
242 | ...
243 |
244 | // enable graceful shutdown with options:
245 | // this option lets the event loop clear to end your node server
246 | // no explicit process.exit() will be triggered.
247 |
248 | gracefulShutdown(server, {
249 | forceExit: false
250 | });
251 | ```
252 |
253 | If you want an explicit process.exit() at the end, set `forceExit` to `true`
254 | (which is the default).
255 |
256 | ### Debug
257 |
258 | If you want to get debug notes ([debug][debug-url] is a dependency of this
259 | module), just set the DEBUG environment variable to enable debugging:
260 |
261 | ```
262 | export DEBUG=http-graceful-shutdown
263 | ```
264 |
265 | OR on Windows:
266 |
267 | ```
268 | set DEBUG=http-graceful-shutdown
269 | ```
270 |
271 | ## Examples
272 |
273 | You can find examples how to use `http-graceful-shutdown` with Express, Koa,
274 | http, http2, fastify in the `examples` directory. To run the examples, be sure
275 | to install debug and express, koa or fastify.
276 |
277 | ```
278 | npm install debug express koa fastify
279 | ```
280 |
281 | ## Version history
282 |
283 | | Version | Date | Comment |
284 | | ------- | ---------- | ----------------------------------------------------------------- |
285 | | 3.1.14 | 2025-01-03 | updated docs |
286 | | 3.1.13 | 2023-02-11 | fix forceExit default value |
287 | | 3.1.12 | 2022-12-04 | changed lgtm to github scanning |
288 | | 3.1.11 | 2022-11-18 | updated examples |
289 | | 3.1.10 | 2022-11-17 | forceExit handling adapted |
290 | | 3.1.9 | 2022-10-24 | updated docs, code cleanup |
291 | | 3.1.8 | 2022-07-27 | updated docs, fixed typos |
292 | | 3.1.7 | 2022-03-18 | updated dependencies, updated docs |
293 | | 3.1.6 | 2022-02-27 | updated dependencies |
294 | | 3.1.5 | 2021-11-08 | updated docs |
295 | | 3.1.4 | 2021-08-27 | updated docs |
296 | | 3.1.3 | 2021-08-03 | fixed handle events once (thanks to Igor Basov) |
297 | | 3.1.2 | 2021-06-15 | fixed cleanupHttp() no timeout |
298 | | 3.1.1 | 2021-05-13 | updated docs |
299 | | 3.1.0 | 2021-05-08 | refactoring, added preShutdown |
300 | | 3.0.2 | 2021-04-08 | updated docs |
301 | | 3.0.1 | 2021-02-26 | code cleanup |
302 | | 3.0.0 | 2021-02-25 | version 3.0 release |
303 | | 2.4.0 | 2021-02-15 | added forceExit option (defaults to true) |
304 | | 2.3.2 | 2019-06-14 | typescript typings fix |
305 | | 2.3.1 | 2019-05-31 | updated docs, added typescript typings |
306 | | 2.3.0 | 2019-05-30 | added manual shutdown (for tests) see docs below |
307 | | 2.2.3 | 2019-02-01 | updated docs, debug |
308 | | 2.2.2 | 2018-12-28 | updated docs, keywords |
309 | | 2.2.1 | 2018-11-20 | updated docs |
310 | | 2.2.0 | 2018-11-19 | added (optional) signal type to shutdown function - see example |
311 | | 2.1.3 | 2018-11-06 | updated docs |
312 | | 2.1.2 | 2018-11-03 | updated dependencies (version bump), updated docs |
313 | | 2.1.1 | 2018-02-28 | extended `isFunction` to support e.g. AsyncFunctions |
314 | | 2.1.0 | 2018-02-11 | bug fixing onShutdown method was called before `server.close` |
315 | | 2.0.6 | 2017-11-06 | updated docs, code cleanup |
316 | | 2.0.5 | 2017-11-06 | updated dependencies, modifications gitignore, added docs |
317 | | 2.0.4 | 2017-09-21 | updated dependencies, modifications gitignore |
318 | | 2.0.3 | 2017-06-18 | updated dependencies |
319 | | 2.0.2 | 2017-05-27 | fixed return value 0 |
320 | | 2.0.1 | 2017-04-24 | modified documentation |
321 | | 2.0.0 | 2017-04-24 | added 'onShutdown' option, renamed 'callback' option to 'finally' |
322 | | 1.0.6 | 2016-02-03 | adding more explicit debug information and documentation |
323 | | 1.0.5 | 2016-02-01 | better handling of closing connections |
324 | | 1.0.4 | 2015-10-01 | small fixes |
325 | | 1.0.3 | 2015-09-15 | updated docs |
326 | | 1.0.1 | 2015-09-14 | updated docs, reformated code |
327 | | 1.0.0 | 2015-09-14 | initial release |
328 |
329 | ## Comments
330 |
331 | If you have ideas, comments or questions, please do not hesitate to contact me.
332 |
333 | Sincerely,
334 |
335 | Sebastian Hildebrandt, [+innovations](http://www.plus-innovations.com)
336 |
337 | ## Credits
338 |
339 | Written by Sebastian Hildebrandt
340 | [sebhildebrandt](https://github.com/sebhildebrandt)
341 |
342 | #### Contributors
343 |
344 | - Deepak Bhattarai [bring2dip](https://github.com/bring2dip)
345 | - Shen [shenfe](https://github.com/shenfe)
346 | - Jeff Hansen [jeffijoe](https://github.com/jeffijoe)
347 | - Igor Basov [IgorBasov](https://github.com/IgorBasov)
348 |
349 | ## License [![MIT license][license-img]][license-url]
350 |
351 | > The [`MIT`][license-url] License (MIT)
352 | >
353 | > Copyright © 2015-2025 Sebastian Hildebrandt,
354 | > [+innovations](http://www.plus-innovations.com).
355 | >
356 | > Permission is hereby granted, free of charge, to any person obtaining a copy
357 | > of this software and associated documentation files (the "Software"), to deal
358 | > in the Software without restriction, including without limitation the rights
359 | > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
360 | > copies of the Software, and to permit persons to whom the Software is
361 | > furnished to do so, subject to the following conditions:
362 | >
363 | > The above copyright notice and this permission notice shall be included in all
364 | > copies or substantial portions of the Software.
365 | >
366 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
367 | > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
368 | > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
369 | > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
370 | > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
371 | > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
372 | > SOFTWARE.
373 |
374 | [npm-image]: https://img.shields.io/npm/v/http-graceful-shutdown.svg?style=flat-square
375 | [npm-url]: https://npmjs.org/package/http-graceful-shutdown
376 | [downloads-image]: https://img.shields.io/npm/dm/http-graceful-shutdown.svg?style=flat-square
377 | [downloads-url]: https://npmjs.org/package/http-graceful-shutdown
378 | [license-url]: https://github.com/sebhildebrandt/http-graceful-shutdown/blob/master/LICENSE
379 | [license-img]: https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square
380 | [npmjs-license]: https://img.shields.io/npm/l/http-graceful-shutdown.svg?style=flat-square
381 | [caretaker-url]: https://github.com/sebhildebrandt
382 | [caretaker-image]: https://img.shields.io/badge/caretaker-sebhildebrandt-blue.svg?style=flat-square
383 | [nodejs-url]: https://nodejs.org/en/
384 | [express-url]: https://github.com/strongloop/expressjs.com
385 | [koa-url]: https://github.com/koajs/koa
386 | [fastify-url]: https://www.fastify.io
387 | [http-url]: https://nodejs.org/api/http.html
388 | [http2-url]: https://nodejs.org/api/http2.html
389 | [debug-url]: https://github.com/visionmedia/debug
390 | [dependencies-url]: https://www.npmjs.com/package/http-graceful-shutdown?activeTab=dependencies
391 | [dependencies-img]: https://img.shields.io/librariesio/release/npm/http-graceful-shutdown.svg?style=flat-square
392 | [daviddm-url]: https://david-dm.org/sebhildebrandt/http-graceful-shutdown
393 | [daviddm-img]: https://img.shields.io/david/sebhildebrandt/http-graceful-shutdown.svg?style=flat-square
394 | [issues-img]: https://img.shields.io/github/issues/sebhildebrandt/http-graceful-shutdown.svg?style=flat-square
395 | [issues-url]: https://github.com/sebhildebrandt/http-graceful-shutdown/issues
396 | [closed-issues-img]: https://img.shields.io/github/issues-closed-raw/sebhildebrandt/http-graceful-shutdown.svg?style=flat-square&color=brightgreen
397 | [closed-issues-url]: https://github.com/sebhildebrandt/http-graceful-shutdown/issues?q=is%3Aissue+is%3Aclosed
398 |
--------------------------------------------------------------------------------
/docs/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Code of Conduct
2 |
3 | As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4 |
5 | We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
6 |
7 | Examples of unacceptable behavior by participants include:
8 |
9 | * The use of sexualized language or imagery
10 | * Personal attacks
11 | * Trolling or insulting/derogatory comments
12 | * Public or private harassment
13 | * Publishing other's private information, such as physical or electronic addresses, without explicit permission
14 | * Other unethical or unprofessional conduct.
15 |
16 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.
17 |
18 | This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
19 |
20 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
21 |
22 | This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)
23 |
--------------------------------------------------------------------------------
/docs/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## You want to contribute some code?
2 |
3 | We are always looking for quality contributions and will be happy to accept your pull requests as long as they adhere to some basic rules:
4 |
5 | * Please make sure that your contribution fits well in the project's context:
6 | * we are aiming to provide a high quality multi platform library, without as less as possible dependencies
7 |
8 | * Please assure that you are submitting quality code, specifically make sure that:
9 | * your commits should not be braking changes - if possible.
10 | * your PR are well testet
11 | * if your commit needs a major version bump (breaking change), please leave a clear message in your comments
12 |
--------------------------------------------------------------------------------
/docs/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ### Issue Type
2 |
3 | Describe your bug here ...
4 | ### Expected behavior
5 |
6 | -
7 | -
8 | -
9 |
10 | ### Actual behavior
11 |
12 | -
13 | -
14 | -
15 |
16 | ### Steps to reproduce the problem
17 |
18 | -
19 | -
20 | -
21 |
22 | ### Specifications
23 |
24 | - package version:
25 | - operating system:
26 | - hardware:
27 |
28 | ### Problem and possible solution
29 |
30 | If you have a solution in mind (or any idea what could cause this issue), we would be happy, if you can describe it here ...
31 |
--------------------------------------------------------------------------------
/docs/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Pull Request
2 |
3 | Fixes #
4 |
5 | #### Changes proposed:
6 |
7 | Specify weather this is a fix / enhancement / update
8 |
9 | #### Description (what is this PR about)
10 |
11 | Brief explanation of the changes you have made and/or the new content you are contributing.
12 |
13 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | # Examples
2 |
3 |
4 | Here you find examples how to use http-graceful-shutdown with `Express`, `Koa`, `http`, `http2`, `fastify`.
5 |
6 | ## Prerequisites
7 |
8 | To run the examples, be sure to install debug and express, koa or fastify.
9 |
10 | ```
11 | npm install debug express koa fastify
12 | ```
13 |
14 | ## Starting Examples
15 |
16 | Then you can start each of the examples, e.g.:
17 |
18 | ```
19 | node express-simple-server.js
20 | node express-advanced-server.js
21 | node express-noexit-server.js
22 | node fastify-simple-server.js
23 | node koa-simple-server.js
24 | node http-simple-server.js
25 | node http2-simple-server.js
26 | ```
27 |
28 | To stop each of the application (and see `http-graceful-shutdown` in action), just press `CTRL-C`. Just have a look at the source code of each of the examples to see details how to use and configure `http-graceful-shutdown`.
29 |
--------------------------------------------------------------------------------
/examples/express-advanced-server.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const gracefulShutdown = require('../lib/index');
3 | const app = express();
4 | const port = 3000;
5 |
6 | const server = app.listen(port, () => {
7 | console.log('HTTP-GRACEFUL-SHUTDOWN');
8 | console.log('-------------------------------------------');
9 | console.log('Advanced EXPRESS test using advanced options and cleanup function');
10 | console.log(`Listening at http://localhost:${port}`);
11 | console.log();
12 | console.log('Press Ctrl-C to test shutdown');
13 | });
14 |
15 | app.get('/', (req, res) => {
16 | setTimeout(() => {
17 | res.send('Hello World!');
18 | }, 15000);
19 |
20 | });
21 |
22 | // personal preShutdown function
23 | // - must return a promise
24 | // - the input parameter is optional (only needed if you want to
25 | // access the signal type inside this function)
26 | // - used, when you need to have HTTP sockets still available and untouched by shutdown process
27 | // - this function here in this example takes 500ms to complete
28 | function preShutdown(signal) {
29 | return new Promise((resolve) => {
30 | console.log();
31 | console.log('"preShutdown" function');
32 | console.log('... called signal: ' + signal);
33 | console.log('... for 500 ms');
34 | console.log('...');
35 | setTimeout(function () {
36 | console.log('... preShutdown finished');
37 | resolve();
38 | }, 500);
39 | });
40 | }
41 | // personal cleanup function
42 | // - must return a promise
43 | // - the input parameter is optional (only needed if you want to
44 | // access the signal type inside this function)
45 | // - this function here in this example takes one second to complete
46 | function cleanup(signal) {
47 | return new Promise((resolve) => {
48 | console.log();
49 | console.log('"onShutdown" function');
50 | console.log('... called signal: ' + signal);
51 | console.log('... in cleanup');
52 | console.log('... for 5 seconds');
53 | console.log('...');
54 | setTimeout(function () {
55 | console.log('... cleanup finished');
56 | resolve();
57 | }, 5000);
58 | });
59 | }
60 |
61 | // this enables the graceful shutdown with advanced options
62 | gracefulShutdown(server,
63 | {
64 | signals: 'SIGINT SIGTERM',
65 | timeout: 3000,
66 | development: false,
67 | preShutdown: preShutdown,
68 | onShutdown: cleanup,
69 | forceExit: true,
70 | finally: function () {
71 | console.log();
72 | console.log('In "finally" function');
73 | console.log('Server graceful shut down completed.');
74 | }
75 | }
76 | );
77 |
--------------------------------------------------------------------------------
/examples/express-noexit-server.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const gracefulShutdown = require('../lib/index');
3 | const app = express();
4 | const port = 3000;
5 |
6 | const server = app.listen(port, () => {
7 | console.log('HTTP-GRACEFUL-SHUTDOWN');
8 | console.log('-----------------------------------------');
9 | console.log('Simple EXPRESS test - no force exit');
10 | console.log('Here we do not force process.exit()');
11 | console.log('Instead, we rely on event loop to clear up');
12 | console.log();
13 | console.log(`Listening at http://localhost:${port}`);
14 | console.log();
15 | console.log('Press Ctrl-C to test shutdown');
16 | });
17 |
18 | app.get('/', (req, res) => {
19 | res.send('Hello World!');
20 | });
21 |
22 | gracefulShutdown(server,
23 | {
24 | forceExit: false, // do not perform process.exit()
25 | finally: function () {
26 | console.log();
27 | console.log('Server graceful shut down completed.');
28 | }
29 | }
30 | );
31 |
32 |
--------------------------------------------------------------------------------
/examples/express-simple-server.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const gracefulShutdown = require('../lib/index');
3 | const app = express();
4 | const port = 3000;
5 |
6 | const server = app.listen(port, () => {
7 | console.log('HTTP-GRACEFUL-SHUTDOWN');
8 | console.log('-----------------------------------------');
9 | console.log('Simple EXPRESS test using default options');
10 | console.log(`Listening at http://localhost:${port}`);
11 | console.log();
12 | console.log('Press Ctrl-C to test shutdown');
13 | });
14 |
15 | app.get('/', (req, res) => {
16 | res.send('Hello World!');
17 | });
18 |
19 | gracefulShutdown(server,
20 | {
21 | finally: function () {
22 | console.log();
23 | console.log('Server graceful shut down completed.');
24 | }
25 | }
26 | );
27 |
28 |
--------------------------------------------------------------------------------
/examples/fastity-simple-server.js:
--------------------------------------------------------------------------------
1 | const Fastify = require('fastify');
2 | const gracefulShutdown = require('../lib/index');
3 | const port = 3000;
4 |
5 | const fastify = Fastify();
6 |
7 | // Declare a route
8 | fastify.get('/', function (request, reply) {
9 | reply.send({ hello: 'world' });
10 | });
11 |
12 | // Run the server!
13 | fastify.listen(port, function (err, address) {
14 | if (err) {
15 | fastify.log.error(err);
16 | process.exit(1);
17 | }
18 | console.log('HTTP-GRACEFUL-SHUTDOWN');
19 | console.log('-------------------------------------------');
20 | console.log('Simple FASTIFY test using default options');
21 | console.log(`Listening at http://localhost:${port}`);
22 | console.log();
23 | console.log('Press Ctrl-C to test shutdown');
24 | });
25 |
26 | gracefulShutdown(fastify.server,
27 | {
28 | finally: function () {
29 | console.log();
30 | console.log('Server graceful shut down completed.');
31 | }
32 | }
33 | );
34 |
35 |
--------------------------------------------------------------------------------
/examples/http-simple-server.js:
--------------------------------------------------------------------------------
1 | const http = require('http');
2 | const gracefulShutdown = require('../lib/index');
3 | const port = 3000;
4 |
5 | const server = http.createServer((req, res) => {
6 | res.setHeader('Content-Type', 'text/html; charset=utf-8');
7 | res.writeHead(200);
8 | res.end('Hello World');
9 | });
10 |
11 | server.listen(port, () => {
12 | console.log('HTTP-GRACEFUL-SHUTDOWN');
13 | console.log('-----------------------------------------');
14 | console.log('Simple HTTP test using default options');
15 | console.log(`Listening at http://localhost:${port}`);
16 | console.log();
17 | console.log('Press Ctrl-C to test shutdown');
18 | });
19 |
20 | gracefulShutdown(server,
21 | {
22 | finally: function () {
23 | console.log();
24 | console.log('Server graceful shut down completed.');
25 | }
26 | }
27 | );
28 |
29 |
--------------------------------------------------------------------------------
/examples/http2-simple-server.js:
--------------------------------------------------------------------------------
1 | const http2 = require('http2');
2 | const gracefulShutdown = require('../lib/index');
3 | const port = 3000;
4 |
5 | const server = http2.createServer();
6 |
7 | server.on('stream', (stream, headers) => {
8 | stream.respond({
9 | 'content-type': 'text/html; charset=utf-8',
10 | ':status': 200
11 | });
12 | stream.end('