Merge "LOG SQL dump files getting installed"
[sdnc/oam.git] / dgbuilder / dgeflows / node_modules / body-parser / node_modules / raw-body / index.js
1 var bytes = require('bytes')
2 var iconv = require('iconv-lite')
3
4 module.exports = function (stream, options, done) {
5   if (options === true || typeof options === 'string') {
6     // short cut for encoding
7     options = {
8       encoding: options
9     }
10   }
11
12   options = options || {}
13
14   if (typeof options === 'function') {
15     done = options
16     options = {}
17   }
18
19   // get encoding
20   var encoding = options.encoding !== true
21     ? options.encoding
22     : 'utf-8'
23
24   // convert the limit to an integer
25   var limit = null
26   if (typeof options.limit === 'number')
27     limit = options.limit
28   if (typeof options.limit === 'string')
29     limit = bytes(options.limit)
30
31   // convert the expected length to an integer
32   var length = null
33   if (options.length != null && !isNaN(options.length))
34     length = parseInt(options.length, 10)
35
36   // check the length and limit options.
37   // note: we intentionally leave the stream paused,
38   // so users should handle the stream themselves.
39   if (limit !== null && length !== null && length > limit) {
40     var err = makeError('request entity too large', 'entity.too.large')
41     err.status = err.statusCode = 413
42     err.length = err.expected = length
43     err.limit = limit
44     cleanup()
45     halt(stream)
46     process.nextTick(function () {
47       done(err)
48     })
49     return defer
50   }
51
52   // streams1: assert request encoding is buffer.
53   // streams2+: assert the stream encoding is buffer.
54   //   stream._decoder: streams1
55   //   state.encoding: streams2
56   //   state.decoder: streams2, specifically < 0.10.6
57   var state = stream._readableState
58   if (stream._decoder || (state && (state.encoding || state.decoder))) {
59     // developer error
60     var err = makeError('stream encoding should not be set',
61       'stream.encoding.set')
62     err.status = err.statusCode = 500
63     cleanup()
64     halt(stream)
65     process.nextTick(function () {
66       done(err)
67     })
68     return defer
69   }
70
71   var received = 0
72   var decoder
73
74   try {
75     decoder = getDecoder(encoding)
76   } catch (err) {
77     cleanup()
78     halt(stream)
79     process.nextTick(function () {
80       done(err)
81     })
82     return defer
83   }
84
85   var buffer = decoder
86     ? ''
87     : []
88
89   stream.on('data', onData)
90   stream.once('end', onEnd)
91   stream.once('error', onEnd)
92   stream.once('close', cleanup)
93
94   return defer
95
96   // yieldable support
97   function defer(fn) {
98     done = fn
99   }
100
101   function onData(chunk) {
102     received += chunk.length
103     decoder
104       ? buffer += decoder.write(chunk)
105       : buffer.push(chunk)
106
107     if (limit !== null && received > limit) {
108       var err = makeError('request entity too large', 'entity.too.large')
109       err.status = err.statusCode = 413
110       err.received = received
111       err.limit = limit
112       cleanup()
113       halt(stream)
114       done(err)
115     }
116   }
117
118   function onEnd(err) {
119     if (err) {
120       cleanup()
121       halt(stream)
122       done(err)
123     } else if (length !== null && received !== length) {
124       err = makeError('request size did not match content length',
125         'request.size.invalid')
126       err.status = err.statusCode = 400
127       err.received = received
128       err.length = err.expected = length
129       cleanup()
130       done(err)
131     } else {
132       var string = decoder
133         ? buffer + (decoder.end() || '')
134         : Buffer.concat(buffer)
135       cleanup()
136       done(null, string)
137     }
138   }
139
140   function cleanup() {
141     received = buffer = null
142
143     stream.removeListener('data', onData)
144     stream.removeListener('end', onEnd)
145     stream.removeListener('error', onEnd)
146     stream.removeListener('close', cleanup)
147   }
148 }
149
150 function getDecoder(encoding) {
151   if (!encoding) return null
152
153   try {
154     return iconv.getCodec(encoding).decoder()
155   } catch (e) {
156     var err = makeError('specified encoding unsupported', 'encoding.unsupported')
157     err.status = err.statusCode = 415
158     err.encoding = encoding
159     throw err
160   }
161 }
162
163 /**
164  * Halt a stream.
165  *
166  * @param {Object} stream
167  * @api private
168  */
169
170 function halt(stream) {
171   // unpipe everything from the stream
172   unpipe(stream)
173
174   // pause stream
175   if (typeof stream.pause === 'function') {
176     stream.pause()
177   }
178 }
179
180 // to create serializable errors you must re-set message so
181 // that it is enumerable and you must re configure the type
182 // property so that is writable and enumerable
183 function makeError(message, type) {
184   var error = new Error()
185   error.message = message
186   Object.defineProperty(error, 'type', {
187     value: type,
188     enumerable: true,
189     writable: true,
190     configurable: true
191   })
192   return error
193 }
194
195 /**
196  * Unpipe everything from a stream.
197  *
198  * @param {Object} stream
199  * @api private
200  */
201
202 /* istanbul ignore next: implementation differs between versions */
203 function unpipe(stream) {
204   if (typeof stream.unpipe === 'function') {
205     // new-style
206     stream.unpipe()
207     return
208   }
209
210   // Node.js 0.8 hack
211   var listener
212   var listeners = stream.listeners('close')
213
214   for (var i = 0; i < listeners.length; i++) {
215     listener = listeners[i]
216
217     if (listener.name !== 'cleanup' && listener.name !== 'onclose') {
218       continue
219     }
220
221     // invoke the listener
222     listener.call(stream)
223   }
224 }