From 705673d634818727dbdb25ee999560970bd268a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?TZ=20=7C=20=E5=A4=A9=E7=8C=AA?= Date: Tue, 24 Mar 2020 13:41:32 +0800 Subject: [PATCH] feat: support xml (#131) --- README.md | 3 +- index.js | 12 +++++++ test/middleware.test.js | 72 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 83 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 36ac290..d287cea 100644 --- a/README.md +++ b/README.md @@ -48,11 +48,12 @@ app.use(async ctx => { ## Options -* **enableTypes**: parser will only parse when request type hits enableTypes, default is `['json', 'form']`. +* **enableTypes**: parser will only parse when request type hits enableTypes, support `json/form/text/xml`, default is `['json', 'form']`. * **encoding**: requested encoding. Default is `utf-8` by `co-body`. * **formLimit**: limit of the `urlencoded` body. If the body ends up being larger than this limit, a 413 error code is returned. Default is `56kb`. * **jsonLimit**: limit of the `json` body. Default is `1mb`. * **textLimit**: limit of the `text` body. Default is `1mb`. +* **xmlLimit**: limit of the `xml` body. Default is `1mb`. * **strict**: when set to true, JSON parser will only accept arrays and objects. Default is `true`. See [strict mode](https://github.com/cojs/co-body#options) in `co-body`. In strict mode, `ctx.request.body` will always be an object(or array), this avoid lots of type judging. But text body will always return string type. * **detectJSON**: custom json request detect function. Default is `null`. diff --git a/index.js b/index.js index 309bfe9..b11d535 100644 --- a/index.js +++ b/index.js @@ -34,6 +34,7 @@ module.exports = function (opts) { var enableForm = checkEnable(enableTypes, 'form'); var enableJson = checkEnable(enableTypes, 'json'); var enableText = checkEnable(enableTypes, 'text'); + var enableXml = checkEnable(enableTypes, 'xml'); opts.detectJSON = undefined; opts.onerror = undefined; @@ -59,15 +60,23 @@ module.exports = function (opts) { 'text/plain', ]; + // default xml types + var xmlTypes = [ + 'text/xml', + 'application/xml', + ]; + var jsonOpts = formatOptions(opts, 'json'); var formOpts = formatOptions(opts, 'form'); var textOpts = formatOptions(opts, 'text'); + var xmlOpts = formatOptions(opts, 'xml'); var extendTypes = opts.extendTypes || {}; extendType(jsonTypes, extendTypes.json); extendType(formTypes, extendTypes.form); extendType(textTypes, extendTypes.text); + extendType(xmlTypes, extendTypes.xml); return async function bodyParser(ctx, next) { if (ctx.request.body !== undefined) return await next(); @@ -96,6 +105,9 @@ module.exports = function (opts) { if (enableText && ctx.request.is(textTypes)) { return await parse.text(ctx, textOpts) || ''; } + if (enableXml && ctx.request.is(xmlTypes)) { + return await parse.text(ctx, xmlOpts) || ''; + } return {}; } }; diff --git a/test/middleware.test.js b/test/middleware.test.js index 13f029a..a7e78de 100644 --- a/test/middleware.test.js +++ b/test/middleware.test.js @@ -210,8 +210,56 @@ describe('test/middleware.test.js', function () { }); }); - describe('extent type', function () { - it('should extent json ok', function (done) { + describe('xml body', function () { + it('should parse xml body ok', function (done) { + var app = App({ + enableTypes: ['xml'], + }); + app.use(async (ctx) => { + ctx.headers['content-type'].should.equal('application/xml'); + ctx.request.body.should.equal('abc'); + ctx.request.rawBody.should.equal('abc'); + ctx.body = ctx.request.body; + }); + request(app.listen()) + .post('/') + .type('xml') + .send('abc') + .expect('abc', done); + }); + + it('should not parse text body when disable', function (done) { + var app = App(); + app.use(async (ctx) => { + ctx.headers['content-type'].should.equal('application/xml'); + ctx.body = ctx.request.body; + }); + request(app.listen()) + .post('/') + .type('xml') + .send('abc') + .expect({}, done); + }); + + it('should xml body reach the limit size', function (done) { + var app = App({ + enableTypes: ['xml'], + xmlLimit: 10, + }); + app.use(async (ctx) => { + ctx.headers['content-type'].should.equal('application/xml'); + ctx.body = ctx.request.body; + }); + request(app.listen()) + .post('/') + .type('xml') + .send('abcdefghijklmn') + .expect(413, done); + }); + }); + + describe('extend type', function () { + it('should extend json ok', function (done) { var app = App({ extendTypes: { json: 'application/x-javascript' @@ -228,7 +276,7 @@ describe('test/middleware.test.js', function () { .expect({ foo: 'bar' }, done); }); - it('should extent json with array ok', function (done) { + it('should extend json with array ok', function (done) { var app = App({ extendTypes: { json: ['application/x-javascript', 'application/y-javascript'] @@ -244,6 +292,24 @@ describe('test/middleware.test.js', function () { .send(JSON.stringify({ foo: 'bar' })) .expect({ foo: 'bar' }, done); }); + + it('should extend xml ok', function (done) { + var app = App({ + enableTypes: ['xml'], + extendTypes: { + xml: 'application/xml-custom' + } + }); + app.use(async (ctx) => { + ctx.body = ctx.request.body; + }); + + request(app.listen()) + .post('/') + .type('application/xml-custom') + .send('abc') + .expect('abc', done); + }); }); describe('enableTypes', function () {