Merge "LOG SQL dump files getting installed"
[sdnc/oam.git] / dgbuilder / dgeflows / node_modules / express / node_modules / finalhandler / index.js
1 /*!
2  * finalhandler
3  * Copyright(c) 2014 Douglas Christopher Wilson
4  * MIT Licensed
5  */
6
7 /**
8  * Module dependencies.
9  */
10
11 var debug = require('debug')('finalhandler')
12 var escapeHtml = require('escape-html')
13 var http = require('http')
14 var onFinished = require('on-finished')
15
16 /**
17  * Variables.
18  */
19
20 /* istanbul ignore next */
21 var defer = typeof setImmediate === 'function'
22   ? setImmediate
23   : function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) }
24 var isFinished = onFinished.isFinished
25
26 /**
27  * Module exports.
28  */
29
30 module.exports = finalhandler
31
32 /**
33  * Final handler:
34  *
35  * @param {Request} req
36  * @param {Response} res
37  * @param {Object} [options]
38  * @return {Function}
39  * @api public
40  */
41
42 function finalhandler(req, res, options) {
43   options = options || {}
44
45   // get environment
46   var env = options.env || process.env.NODE_ENV || 'development'
47
48   // get error callback
49   var onerror = options.onerror
50
51   return function (err) {
52     var msg
53
54     // ignore 404 on in-flight response
55     if (!err && res._header) {
56       debug('cannot 404 after headers sent')
57       return
58     }
59
60     // unhandled error
61     if (err) {
62       // default status code to 500
63       if (!res.statusCode || res.statusCode < 400) {
64         res.statusCode = 500
65       }
66
67       // respect err.status
68       if (err.status) {
69         res.statusCode = err.status
70       }
71
72       // production gets a basic error message
73       var msg = env === 'production'
74         ? http.STATUS_CODES[res.statusCode]
75         : err.stack || err.toString()
76       msg = escapeHtml(msg)
77         .replace(/\n/g, '<br>')
78         .replace(/  /g, ' &nbsp;') + '\n'
79     } else {
80       res.statusCode = 404
81       msg = 'Cannot ' + escapeHtml(req.method) + ' ' + escapeHtml(req.originalUrl || req.url) + '\n'
82     }
83
84     debug('default %s', res.statusCode)
85
86     // schedule onerror callback
87     if (err && onerror) {
88       defer(onerror, err, req, res)
89     }
90
91     // cannot actually respond
92     if (res._header) {
93       return req.socket.destroy()
94     }
95
96     send(req, res, res.statusCode, msg)
97   }
98 }
99
100 /**
101  * Send response.
102  *
103  * @param {IncomingMessage} req
104  * @param {OutgoingMessage} res
105  * @param {number} status
106  * @param {string} body
107  * @api private
108  */
109
110 function send(req, res, status, body) {
111   function write() {
112     res.statusCode = status
113
114     // security header for content sniffing
115     res.setHeader('X-Content-Type-Options', 'nosniff')
116
117     // standard headers
118     res.setHeader('Content-Type', 'text/html; charset=utf-8')
119     res.setHeader('Content-Length', Buffer.byteLength(body, 'utf8'))
120
121     if (req.method === 'HEAD') {
122       res.end()
123       return
124     }
125
126     res.end(body, 'utf8')
127   }
128
129   if (isFinished(req)) {
130     write()
131     return
132   }
133
134   // unpipe everything from the request
135   unpipe(req)
136
137   // flush the request
138   onFinished(req, write)
139   req.resume()
140 }
141
142 /**
143  * Unpipe everything from a stream.
144  *
145  * @param {Object} stream
146  * @api private
147  */
148
149 /* istanbul ignore next: implementation differs between versions */
150 function unpipe(stream) {
151   if (typeof stream.unpipe === 'function') {
152     // new-style
153     stream.unpipe()
154     return
155   }
156
157   // Node.js 0.8 hack
158   var listener
159   var listeners = stream.listeners('close')
160
161   for (var i = 0; i < listeners.length; i++) {
162     listener = listeners[i]
163
164     if (listener.name !== 'cleanup' && listener.name !== 'onclose') {
165       continue
166     }
167
168     // invoke the listener
169     listener.call(stream)
170   }
171 }