| 181 | |
| 182 | // returns a promise if no callback is provided |
| 183 | async parse(req, cb) { |
| 184 | this.req = req; |
| 185 | let promise; |
| 186 | |
| 187 | // Setup callback first, so we don't miss anything from data events emitted immediately. |
| 188 | if (!cb) { |
| 189 | let resolveRef; |
| 190 | let rejectRef; |
| 191 | promise = new Promise((resolve, reject) => { |
| 192 | resolveRef = resolve; |
| 193 | rejectRef = reject; |
| 194 | }); |
| 195 | cb = (err, fields, files) => { |
| 196 | if (err) { |
| 197 | rejectRef(err); |
| 198 | } else { |
| 199 | resolveRef([fields, files]); |
| 200 | } |
| 201 | } |
| 202 | } |
| 203 | const callback = once(dezalgo(cb)); |
| 204 | this.fields = {}; |
| 205 | const files = {}; |
| 206 | |
| 207 | this.on('field', (name, value) => { |
| 208 | if (this.type === 'multipart' || this.type === 'urlencoded') { |
| 209 | if (!hasOwnProp(this.fields, name)) { |
| 210 | this.fields[name] = [value]; |
| 211 | } else { |
| 212 | this.fields[name].push(value); |
| 213 | } |
| 214 | } else { |
| 215 | this.fields[name] = value; |
| 216 | } |
| 217 | }); |
| 218 | this.on('file', (name, file) => { |
| 219 | if (!hasOwnProp(files, name)) { |
| 220 | files[name] = [file]; |
| 221 | } else { |
| 222 | files[name].push(file); |
| 223 | } |
| 224 | }); |
| 225 | this.on('error', (err) => { |
| 226 | callback(err, this.fields, files); |
| 227 | }); |
| 228 | this.on('end', () => { |
| 229 | callback(null, this.fields, files); |
| 230 | }); |
| 231 | |
| 232 | // Parse headers and setup the parser, ready to start listening for data. |
| 233 | await this.writeHeaders(req.headers); |
| 234 | |
| 235 | // Start listening for data. |
| 236 | req |
| 237 | .on('error', (err) => { |
| 238 | this._error(err); |
| 239 | }) |
| 240 | .on('aborted', () => { |