UNPKG

6.16 kBMarkdownView Raw
1#await-busboy
2
3[busboy][] multipart parser with `async/await` and [koa][]/[co][] `yield` support.
4
5[![NPM version][npm-image]][npm-url]
6[![build status][travis-image]][travis-url]
7[![Test coverage][codecov-image]][codecov-url]
8[![David deps][david-image]][david-url]
9[![npm download][download-image]][download-url]
10
11[npm-image]: https://img.shields.io/npm/v/await-busboy.svg?style=flat-square
12[npm-url]: https://npmjs.org/package/await-busboy
13[travis-image]: https://img.shields.io/travis/aheckmann/await-busboy.svg?style=flat-square
14[travis-url]: https://travis-ci.org/aheckmann/await-busboy
15[codecov-image]: https://codecov.io/github/aheckmann/await-busboy/coverage.svg?branch=master
16[codecov-url]: https://codecov.io/github/aheckmann/await-busboy?branch=master
17[david-image]: https://img.shields.io/david/aheckmann/await-busboy.svg?style=flat-square
18[david-url]: https://david-dm.org/aheckmann/await-busboy
19[download-image]: https://img.shields.io/npm/dm/await-busboy.svg?style=flat-square
20[download-url]: https://npmjs.org/package/await-busboy
21[busboy]: https://github.com/mscdex/busboy
22[co]: https://github.com/tj/co
23[koa]: https://github.com/koajs/koa
24
25_forked from https://github.com/cojs/busboy and updated to support async/await_
26
27## Example
28
29```js
30const Koa = require('koa')
31const app = new Koa()
32const parse = require('await-busboy')
33
34app.use(async (ctx, next) => {
35 // the body isn't multipart, we can't parse it
36 if (!ctx.request.is('multipart/*')) return await next
37
38 const parts = parse(ctx)
39
40 try {
41 let part
42 while ((part = await parts)) {
43 if (part.length) {
44 // arrays are await-busboy fields
45 console.log({ key: part[0], value: part[1] })
46 } else {
47 // otherwise, it's a stream
48 part.pipe(someOtherStream)
49 }
50 }
51 } catch (err) {
52 return ctx.throw(err)
53 }
54
55 ctx.body = 'await-busboy is done parsing the form!'
56});
57
58app.listen(3000);
59```
60
61Note that parts will be delievered in the order they are defined in the form.
62Put your CSRF token first in the form and your larger files last.
63
64If you want `await-busboy` to automatically handle the fields,
65set the `autoFields: true` option.
66Now all the parts will be streams and a field object and array will automatically be populated.
67
68```js
69const Koa = require('koa')
70const app = new Koa()
71const parse = require('await-busboy')
72
73app.use(async (ctx, next) => {
74 const parts = parse(ctx, {
75 autoFields: true
76 })
77
78 try {
79 let part
80 while ((part = await parts)) {
81 // it's a stream
82 part.pipe(fs.createWriteStream('some file.txt'))
83 }
84 } catch (err) {
85 return ctx.throw(err)
86 }
87
88 ctx.body = 'and we are done parsing the form!'
89
90 // .field holds all the fields in key/value form
91 console.log(parts.field._csrf)
92
93 // .fields holds all the fields in [key, value] form
94 console.log(parts.fields[0])
95})
96```
97
98### Example for csrf check
99
100Use `options.checkField` hook `function(name, val, fieldnameTruncated, valTruncated)`
101can handle fields check.
102
103```js
104const parse = require('await-busboy')
105
106app.use(async (ctx, next) => {
107 const parts = parse(ctx, {
108 checkField: (name, value) => {
109 if (name === '_csrf' && !checkCSRF(ctx, value)) {
110 const err = new Error('invalid csrf token')
111 err.status = 400
112 return err
113 }
114 }
115 })
116
117 let part
118 while ((part = await parts)) {
119 // ...
120 }
121})
122```
123
124### Example for filename extension check
125
126Use `options.checkFile` hook `function(fieldname, file, filename, encoding, mimetype)`
127can handle filename check.
128
129```js
130const parse = require('await-busboy')
131const path = require('path')
132
133app.use(async (ctx, next) {
134 const parts = parse(ctx, {
135 // only allow upload `.jpg` files
136 checkFile: function (fieldname, file, filename) {
137 if (path.extname(filename) !== '.jpg') {
138 const err = new Error('invalid jpg image')
139 err.status = 400
140 return err
141 }
142 }
143 })
144
145 let part
146 while ((part = await parts)) {
147 // ...
148 }
149})
150```
151
152### co, koa and yield support
153
154This module is backward compatible with [koa][], [co][] and `yield` syntax.
155
156```js
157const Koa = require('koa')
158const app = new Koa()
159const parse = require('await-busboy')
160
161app.use(function* (ctx, next) {
162 // the body isn't multipart, we can't parse it
163 if (!ctx.request.is('multipart/*')) return yield next
164
165 const parts = parse(ctx)
166
167 try {
168 let part
169 while ((part = yield parts)) {
170 if (part.length) {
171 // arrays are await-busboy fields
172 console.log({ key: part[0], value: part[1] })
173 } else {
174 // otherwise, it's a stream
175 part.pipe(someOtherStream)
176 }
177 }
178 } catch (err) {
179 return ctx.throw(err)
180 }
181
182 ctx.body = 'await-busboy is done parsing the form!'
183});
184```
185
186## API
187
188### parts = parse(stream, [options])
189
190```js
191const parse = require('await-busboy')
192const parts = parse(stream, {
193 autoFields: true
194})
195```
196
197`options` are passed to [busboy][].
198The only additional option is `autoFields`.
199
200**Note**: If [busboy][] events `partsLimit`, `filesLimit`, `fieldsLimit` is emitted, will throw an error.
201
202### part = await parts
203
204await the next part.
205If `autoFields: true`, this will always be a file stream.
206Otherwise, it will be a [field](https://github.com/mscdex/busboy#busboy-special-events) as an array.
207
208- Readable Stream
209
210 - `fieldname`
211 - `filename`
212 - `transferEncoding` or `encoding`
213 - `mimeType` or `mime`
214
215- Field[]
216
217 0. `fieldname`
218 1. `value`
219 2. `valueTruncated` - `Boolean`
220 3. `fieldnameTruncated` - Boolean
221
222If falsey, then the parser is done.
223
224### parts.field{}
225
226If `autoFields: true`, this object will be populated with key/value pairs.
227
228### parts.fields[]
229
230If `autoFields: true`, this array will be populated with all fields.
231
232## Development
233
234### Running tests
235
236- `npm test` runs tests + code coverage + lint
237- `npm run lint` runs lint only
238- `npm run lint-fix` runs lint and attempts to fix syntax issues
239- `npm run test-cov` runs tests + test coverage
240- `npm run open-cov` opens test coverage results in your browser
241- `npm run test-only` runs tests only
242
243## LICENSE
244
245[MIT](https://github.com/aheckmann/await-busboy/blob/master/LICENSE)