1 | var fs = require('fs'),
|
2 | WritableStream = require('stream').Writable
|
3 | || require('readable-stream').Writable,
|
4 | inherits = require('util').inherits;
|
5 |
|
6 | var parseParams = require('./utils').parseParams;
|
7 |
|
8 | function Busboy(opts) {
|
9 | if (!(this instanceof Busboy))
|
10 | return new Busboy(opts);
|
11 | if (opts.highWaterMark !== undefined)
|
12 | WritableStream.call(this, { highWaterMark: opts.highWaterMark });
|
13 | else
|
14 | WritableStream.call(this);
|
15 |
|
16 | this._done = false;
|
17 | this._parser = undefined;
|
18 |
|
19 | this.opts = opts;
|
20 | if (opts.headers && typeof opts.headers['content-type'] === 'string')
|
21 | this.parseHeaders(opts.headers);
|
22 | else
|
23 | throw new Error('Missing Content-Type');
|
24 | }
|
25 | inherits(Busboy, WritableStream);
|
26 |
|
27 | Busboy.prototype.emit = function(ev) {
|
28 | if (ev === 'finish' && !this._done)
|
29 | this._parser && this._parser.end();
|
30 | else
|
31 | WritableStream.prototype.emit.apply(this, arguments);
|
32 | };
|
33 |
|
34 | Busboy.prototype.parseHeaders = function(headers) {
|
35 | this._parser = undefined;
|
36 | if (headers['content-type']) {
|
37 | var parsed = parseParams(headers['content-type']),
|
38 | matched, type;
|
39 | for (var i = 0; i < TYPES_LEN; ++i) {
|
40 | type = TYPES[i];
|
41 | if (typeof type.detect === 'function')
|
42 | matched = type.detect(parsed);
|
43 | else
|
44 | matched = type.detect.test(parsed[0]);
|
45 | if (matched)
|
46 | break;
|
47 | }
|
48 | if (matched) {
|
49 | var cfg = {
|
50 | limits: this.opts.limits,
|
51 | headers: headers,
|
52 | parsedConType: parsed,
|
53 | highWaterMark: undefined,
|
54 | fileHwm: undefined,
|
55 | defCharset: undefined,
|
56 | preservePath: false
|
57 | };
|
58 | if (this.opts.highWaterMark)
|
59 | cfg.highWaterMark = this.opts.highWaterMark;
|
60 | if (this.opts.fileHwm)
|
61 | cfg.fileHwm = this.opts.fileHwm;
|
62 | cfg.defCharset = this.opts.defCharset;
|
63 | cfg.preservePath = this.opts.preservePath;
|
64 | this._parser = type(this, cfg);
|
65 | return;
|
66 | }
|
67 | }
|
68 | throw new Error('Unsupported content type: ' + headers['content-type']);
|
69 | };
|
70 |
|
71 | Busboy.prototype._write = function(chunk, encoding, cb) {
|
72 | if (!this._parser)
|
73 | return cb(new Error('Not ready to parse. Missing Content-Type?'));
|
74 | this._parser.write(chunk, cb);
|
75 | };
|
76 |
|
77 | var TYPES = [], TYPES_LEN = 0;
|
78 | fs.readdirSync(__dirname + '/types').forEach(function(type) {
|
79 | if (!/\.js$/.test(type))
|
80 | return;
|
81 | var typemod = require(__dirname + '/types/' + type);
|
82 | if (typemod.detect) {
|
83 | TYPES.push(typemod);
|
84 | ++TYPES_LEN;
|
85 | }
|
86 | });
|
87 |
|
88 | module.exports = Busboy;
|