forked from cojs/busboy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
130 lines (103 loc) · 2.98 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
var Busboy = require('busboy')
var chan = require('chan')
var getDescriptor = Object.getOwnPropertyDescriptor
var isArray = Array.isArray;
var slice = [].slice
module.exports = function (request, options) {
var ch = chan()
// koa special sauce
request = request.req || request
this.request = request
var ctx = this
options = options || {}
options.headers = request.headers
var busboy = new Busboy(options)
request.on('close', cleanup)
busboy
.on('field', onField)
.on('file', onFile)
.on('close', cleanup)
.on('error', onEnd)
.on('finish', onEnd)
busboy.on('partsLimit', function(){
var err = new Error('Reach parts limit')
err.code = 'Request_parts_limit'
err.status = 413
onEnd(err)
})
busboy.on('filesLimit', function(){
var err = new Error('Reach files limit')
err.code = 'Request_files_limit'
err.status = 413
onEnd(err)
})
busboy.on('fieldsLimit', function(){
var err = new Error('Reach fields limit')
err.code = 'Request_fields_limit'
err.status = 413
onEnd(err)
})
request.pipe(busboy)
// i would just put everything in an array
// but people will complain
if (options.autoFields) {
var field = ch.field = {} // object lookup
var fields = ch.fields = [] // list lookup
}
return ch
function onField(name, val) {
var args = slice.call(arguments)
if (options.autoFields) {
fields.push(args)
// don't overwrite prototypes
if (getDescriptor(Object.prototype, name)) return
var prev = field[name]
if (prev == null) return field[name] = val
if (isArray(prev)) return prev.push(val)
field[name] = [prev, val]
} else {
ch(args)
}
}
function onFile(fieldname, file, filename, encoding, mimetype) {
// opinionated, but 5 arguments is ridiculous
file.fieldname = fieldname
file.filename = filename
file.transferEncoding = file.encoding = encoding
file.mimeType = file.mime = mimetype
file.fileRead = [];
file.on('data', function(chunk) {
// Push chunks into the fileRead array
this.fileRead.push(chunk);
});
file.on('end', function() {
// Concat the chunks into a Buffer
var finalBuffer = Buffer.concat(this.fileRead);
if (typeof ctx.request.files === 'undefined'){
ctx.request.files = {}
}
ctx.request.files[fieldname] = {
buffer: finalBuffer,
size: finalBuffer.length,
filename: filename,
mimetype: mimetype
};
ch(file)
})
}
function onEnd(err) {
cleanup()
ch(err)
}
function cleanup() {
request.removeListener('close', cleanup)
busboy.removeListener('field', onField)
busboy.removeListener('file', onFile)
busboy.removeListener('close', cleanup)
busboy.removeListener('error', onEnd)
busboy.removeListener('partsLimit', onEnd)
busboy.removeListener('filesLimit', onEnd)
busboy.removeListener('fieldsLimit', onEnd)
busboy.removeListener('finish', onEnd)
}
}