Skip to content

Commit

Permalink
feat: custom multipart parse options per request (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
fengmk2 authored and dead-horse committed Dec 26, 2018
1 parent b50151f commit d7504b9
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 15 deletions.
24 changes: 21 additions & 3 deletions app/extend/context.js
Expand Up @@ -39,6 +39,10 @@ module.exports = {
* create multipart.parts instance, to get separated files.
* @method Context#multipart
* @param {Object} [options] - override default multipart configurations
* - {Boolean} options.autoFields
* - {String} options.defCharset
* - {Object} options.limits
* - {Function} options.checkFile
* @return {Yieldable} parts
*/
multipart(options) {
Expand All @@ -49,8 +53,13 @@ module.exports = {
if (this[HAS_CONSUMED]) throw new TypeError('the multipart request can\'t be consumed twice');

this[HAS_CONSUMED] = true;
const parseOptions = {};
Object.assign(parseOptions, this.app.config.multipartParseOptions, options);
const parseOptions = Object.assign({}, this.app.config.multipartParseOptions);
options = options || {};
if (typeof options.autoFields === 'boolean') parseOptions.autoFields = options.autoFields;
if (options.defCharset) parseOptions.defCharset = options.defCharset;
if (options.checkFile) parseOptions.checkFile = options.checkFile;
// merge and create a new limits object
if (options.limits) parseOptions.limits = Object.assign({}, parseOptions.limits, options.limits);
return parse(this, parseOptions);
},

Expand All @@ -65,12 +74,21 @@ module.exports = {
* @method Context#getFileStream
* @param {Object} options
* - {Boolean} options.requireFile - required file submit, default is true
* - {String} options.defCharset
* - {Object} options.limits
* - {Function} options.checkFile
* @return {ReadStream} stream
* @since 1.0.0
*/
async getFileStream(options) {
options = options || {};
const parts = this.multipart({ autoFields: true });
const multipartOptions = {
autoFields: true,
};
if (options.defCharset) multipartOptions.defCharset = options.defCharset;
if (options.limits) multipartOptions.limits = options.limits;
if (options.checkFile) multipartOptions.checkFile = options.checkFile;
const parts = this.multipart(multipartOptions);
let stream = await parts();

if (options.requireFile !== false) {
Expand Down
6 changes: 5 additions & 1 deletion test/fixtures/apps/upload-one-file/app/controller/async.js
Expand Up @@ -7,7 +7,11 @@ module.exports = app => {
return class UploadController extends app.Controller {
async async() {
const ctx = this.ctx;
const stream = await ctx.getFileStream();
const options = {};
if (ctx.query.fileSize) {
options.limits = { fileSize: parseInt(ctx.query.fileSize) };
}
const stream = await ctx.getFileStream(options);
if (ctx.query.foo === 'error') {
// mock undefined error
stream.foo();
Expand Down
24 changes: 14 additions & 10 deletions test/fixtures/apps/upload-one-file/app/router.js
Expand Up @@ -3,20 +3,24 @@
const path = require('path');
const fs = require('fs');
const is = require('is-type-of');
const pump = require('mz-modules/pump');
const mkdirp = require('mz-modules/mkdirp');

module.exports = app => {
// mock oss
app.context.oss = {
put(name) {
return new Promise(resolve => {
resolve({
name,
url: 'http://mockoss.com/' + name,
res: {
status: 200,
},
});
});
async put(name, stream) {
const tmpfile = path.join(app.config.baseDir, 'run', Date.now() + name);
await mkdirp(path.dirname(tmpfile));
const writeStream = fs.createWriteStream(tmpfile);
await pump(stream, writeStream);
return {
name,
url: 'http://mockoss.com/' + name,
res: {
status: 200,
},
};
},
};

Expand Down
21 changes: 20 additions & 1 deletion test/multipart.test.js
Expand Up @@ -421,8 +421,8 @@ describe('test/multipart.test.js', () => {
dataType: 'json',
});

assert(res.status === 200);
const data = res.data;
assert(res.status === 200);
assert(data.status === 200);
assert(typeof data.name === 'string');
assert(data.url.includes('http://mockoss.com/egg-multipart-test/'));
Expand Down Expand Up @@ -506,6 +506,25 @@ describe('test/multipart.test.js', () => {
yield sleep(100);
}
});

it('should file hit limits fileSize', function* () {
const form = formstream();
form.buffer('file', Buffer.alloc(1024 * 1024 * 100), 'foo.js');

const headers = form.headers();
const url = host + '/upload/async?fileSize=100000';
const result = yield urllib.request(url, {
method: 'POST',
headers,
stream: form,
dataType: 'json',
agent,
});

assert(result.status === 413);
const data = result.data;
assert(data.message === 'Request file too large');
});
});

describe('upload over fileSize limit', () => {
Expand Down

0 comments on commit d7504b9

Please sign in to comment.