README.md
1 # on-finished 2 3 [![NPM Version][npm-version-image]][npm-url] 4 [![NPM Downloads][npm-downloads-image]][npm-url] 5 [![Node.js Version][node-image]][node-url] 6 [![Build Status][ci-image]][ci-url] 7 [![Coverage Status][coveralls-image]][coveralls-url] 8 9 Execute a callback when a HTTP request closes, finishes, or errors. 10 11 ## Install 12 13 This is a [Node.js](https://nodejs.org/en/) module available through the 14 [npm registry](https://www.npmjs.com/). Installation is done using the 15 [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): 16 17 ```sh 18 $ npm install on-finished 19 ``` 20 21 ## API 22 23 ```js 24 var onFinished = require('on-finished') 25 ``` 26 27 ### onFinished(res, listener) 28 29 Attach a listener to listen for the response to finish. The listener will 30 be invoked only once when the response finished. If the response finished 31 to an error, the first argument will contain the error. If the response 32 has already finished, the listener will be invoked. 33 34 Listening to the end of a response would be used to close things associated 35 with the response, like open files. 36 37 Listener is invoked as `listener(err, res)`. 38 39 <!-- eslint-disable handle-callback-err --> 40 41 ```js 42 onFinished(res, function (err, res) { 43 // clean up open fds, etc. 44 // err contains the error if request error'd 45 }) 46 ``` 47 48 ### onFinished(req, listener) 49 50 Attach a listener to listen for the request to finish. The listener will 51 be invoked only once when the request finished. If the request finished 52 to an error, the first argument will contain the error. If the request 53 has already finished, the listener will be invoked. 54 55 Listening to the end of a request would be used to know when to continue 56 after reading the data. 57 58 Listener is invoked as `listener(err, req)`. 59 60 <!-- eslint-disable handle-callback-err --> 61 62 ```js 63 var data = '' 64 65 req.setEncoding('utf8') 66 req.on('data', function (str) { 67 data += str 68 }) 69 70 onFinished(req, function (err, req) { 71 // data is read unless there is err 72 }) 73 ``` 74 75 ### onFinished.isFinished(res) 76 77 Determine if `res` is already finished. This would be useful to check and 78 not even start certain operations if the response has already finished. 79 80 ### onFinished.isFinished(req) 81 82 Determine if `req` is already finished. This would be useful to check and 83 not even start certain operations if the request has already finished. 84 85 ## Special Node.js requests 86 87 ### HTTP CONNECT method 88 89 The meaning of the `CONNECT` method from RFC 7231, section 4.3.6: 90 91 > The CONNECT method requests that the recipient establish a tunnel to 92 > the destination origin server identified by the request-target and, 93 > if successful, thereafter restrict its behavior to blind forwarding 94 > of packets, in both directions, until the tunnel is closed. Tunnels 95 > are commonly used to create an end-to-end virtual connection, through 96 > one or more proxies, which can then be secured using TLS (Transport 97 > Layer Security, [RFC5246]). 98 99 In Node.js, these request objects come from the `'connect'` event on 100 the HTTP server. 101 102 When this module is used on a HTTP `CONNECT` request, the request is 103 considered "finished" immediately, **due to limitations in the Node.js 104 interface**. This means if the `CONNECT` request contains a request entity, 105 the request will be considered "finished" even before it has been read. 106 107 There is no such thing as a response object to a `CONNECT` request in 108 Node.js, so there is no support for one. 109 110 ### HTTP Upgrade request 111 112 The meaning of the `Upgrade` header from RFC 7230, section 6.1: 113 114 > The "Upgrade" header field is intended to provide a simple mechanism 115 > for transitioning from HTTP/1.1 to some other protocol on the same 116 > connection. 117 118 In Node.js, these request objects come from the `'upgrade'` event on 119 the HTTP server. 120 121 When this module is used on a HTTP request with an `Upgrade` header, the 122 request is considered "finished" immediately, **due to limitations in the 123 Node.js interface**. This means if the `Upgrade` request contains a request 124 entity, the request will be considered "finished" even before it has been 125 read. 126 127 There is no such thing as a response object to a `Upgrade` request in 128 Node.js, so there is no support for one. 129 130 ## Example 131 132 The following code ensures that file descriptors are always closed 133 once the response finishes. 134 135 ```js 136 var destroy = require('destroy') 137 var fs = require('fs') 138 var http = require('http') 139 var onFinished = require('on-finished') 140 141 http.createServer(function onRequest (req, res) { 142 var stream = fs.createReadStream('package.json') 143 stream.pipe(res) 144 onFinished(res, function () { 145 destroy(stream) 146 }) 147 }) 148 ``` 149 150 ## License 151 152 [MIT](LICENSE) 153 154 [ci-image]: https://badgen.net/github/checks/jshttp/on-finished/master?label=ci 155 [ci-url]: https://github.com/jshttp/on-finished/actions/workflows/ci.yml 156 [coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/on-finished/master 157 [coveralls-url]: https://coveralls.io/r/jshttp/on-finished?branch=master 158 [node-image]: https://badgen.net/npm/node/on-finished 159 [node-url]: https://nodejs.org/en/download 160 [npm-downloads-image]: https://badgen.net/npm/dm/on-finished 161 [npm-url]: https://npmjs.org/package/on-finished 162 [npm-version-image]: https://badgen.net/npm/v/on-finished