UNPKG

4.78 kBJavaScriptView Raw
1/**
2 * koa-body - index.js
3 * Copyright(c) 2014
4 * MIT Licensed
5 *
6 * @author Daryl Lau (@dlau)
7 * @author Charlike Mike Reagent (@tunnckoCore)
8 * @api private
9 */
10
11'use strict';
12
13/**
14 * Module dependencies.
15 */
16
17var buddy = require('co-body');
18var forms = require('formidable');
19
20/**
21 * Expose `requestbody()`.
22 */
23
24module.exports = requestbody;
25
26/**
27 *
28 * @param {Object} options
29 * @see https://github.com/dlau/koa-body
30 * @api public
31 */
32function requestbody(opts) {
33 opts = opts || {};
34 opts.onError = 'onError' in opts ? opts.onError : false;
35 opts.patchNode = 'patchNode' in opts ? opts.patchNode : false;
36 opts.patchKoa = 'patchKoa' in opts ? opts.patchKoa : true;
37 opts.multipart = 'multipart' in opts ? opts.multipart : false;
38 opts.urlencoded = 'urlencoded' in opts ? opts.urlencoded : true;
39 opts.json = 'json' in opts ? opts.json : true;
40 opts.text = 'text' in opts ? opts.text : true;
41 opts.encoding = 'encoding' in opts ? opts.encoding : 'utf-8';
42 opts.jsonLimit = 'jsonLimit' in opts ? opts.jsonLimit : '1mb';
43 opts.jsonStrict = 'jsonStrict' in opts ? opts.jsonStrict : true;
44 opts.formLimit = 'formLimit' in opts ? opts.formLimit : '56kb';
45 opts.queryString = 'queryString' in opts ? opts.queryString : null;
46 opts.formidable = 'formidable' in opts ? opts.formidable : {};
47 opts.textLimit = 'textLimit' in opts ? opts.textLimit : '56kb';
48 opts.strict = 'strict' in opts ? opts.strict : true;
49
50 return function (ctx, next) {
51 var bodyPromise;
52 // so don't parse the body in strict mode
53 if (!opts.strict || ["GET", "HEAD", "DELETE"].indexOf(ctx.method.toUpperCase()) === -1) {
54 try {
55 if (opts.json && ctx.is('json')) {
56 bodyPromise = buddy.json(ctx, {
57 encoding: opts.encoding,
58 limit: opts.jsonLimit,
59 strict: opts.jsonStrict
60 });
61 } else if (opts.urlencoded && ctx.is('urlencoded')) {
62 bodyPromise = buddy.form(ctx, {
63 encoding: opts.encoding,
64 limit: opts.formLimit,
65 queryString: opts.queryString
66 });
67 } else if (opts.text && ctx.is('text')) {
68 bodyPromise = buddy.text(ctx, {
69 encoding: opts.encoding,
70 limit: opts.textLimit
71 });
72 } else if (opts.multipart && ctx.is('multipart')) {
73 bodyPromise = formy(ctx, opts.formidable);
74 }
75 } catch (parsingError) {
76 if (typeof opts.onError === 'function') {
77 opts.onError(parsingError, ctx);
78 } else {
79 throw parsingError;
80 }
81 }
82 }
83
84 bodyPromise = bodyPromise || Promise.resolve({});
85 return bodyPromise.catch(function(parsingError) {
86 if (typeof opts.onError === 'function') {
87 opts.onError(parsingError, ctx);
88 } else {
89 throw parsingError;
90 }
91 return next();
92 })
93 .then(function(body) {
94 if (opts.patchNode) {
95 if (isMultiPart(ctx, opts)) {
96 ctx.req.body = body.fields;
97 ctx.req.files = body.files;
98 } else {
99 ctx.req.body = body;
100 }
101 }
102 if (opts.patchKoa) {
103 if (isMultiPart(ctx, opts)) {
104 ctx.request.body = body.fields;
105 ctx.request.files = body.files;
106 } else {
107 ctx.request.body = body;
108 }
109 }
110 return next();
111 })
112 };
113}
114
115/**
116 * Check if multipart handling is enabled and that this is a multipart request
117 *
118 * @param {Object} ctx
119 * @param {Object} opts
120 * @return {Boolean} true if request is multipart and being treated as so
121 * @api private
122 */
123function isMultiPart(ctx, opts) {
124 return opts.multipart && ctx.is('multipart');
125}
126
127/**
128 * Donable formidable
129 *
130 * @param {Stream} ctx
131 * @param {Object} opts
132 * @return {Promise}
133 * @api private
134 */
135function formy(ctx, opts) {
136 return new Promise(function (resolve, reject) {
137 var fields = {};
138 var files = {};
139 var form = new forms.IncomingForm(opts);
140 form.on('end', function () {
141 return resolve({
142 fields: fields,
143 files: files
144 });
145 }).on('error', function (err) {
146 return reject(err);
147 }).on('field', function (field, value) {
148 if (fields[field]) {
149 if (Array.isArray(fields[field])) {
150 fields[field].push(value);
151 } else {
152 fields[field] = [fields[field], value];
153 }
154 } else {
155 fields[field] = value;
156 }
157 }).on('file', function (field, file) {
158 if (files[field]) {
159 if (Array.isArray(files[field])) {
160 files[field].push(file);
161 } else {
162 files[field] = [files[field], file];
163 }
164 } else {
165 files[field] = file;
166 }
167 });
168 if (opts.onFileBegin) {
169 form.on('fileBegin', opts.onFileBegin);
170 }
171 form.parse(ctx.req);
172 });
173}