simplify body parsing example

for the average use-case
This commit is contained in:
TJ Holowaychuk 2013-12-08 10:50:57 -08:00
parent 70df2fd232
commit abeabcc268
3 changed files with 26 additions and 128 deletions

View File

@ -1,62 +1,19 @@
/**
* Example for handling JSON and urlencoded request bodies.
* All the throws at the beginning of the middleware are all app-dependent and may not be suited for your use-case.
* For the actual body parsing (yield rawBody and down),
* you most may be interested in modules that already do this for you:
*
* - [body](https://github.com/raynos/body)
* - [co-body](https://github.com/visionmedia/co-body)
*/
var koa = require('koa');
var qs = require('querystring');
var rawBody = require('raw-body');
var parse = require('co-body');
var app = module.exports = koa();
// only json requests
// POST .name to /uppercase
// co-body accepts application/json
// and application/x-www-form-urlencoded
app.use(function *(next){
if (this.path !== '/json') return yield next;
if (this.length == 0) this.throw(400, 'no request body');
if (this.length == null) this.throw(411, 'content length required');
if (!this.is('application/json')) this.throw(415, 'json bodies only');
var body = yield rawBody(this.req, {
length: this.length,
limit: 25, // bytes
encoding: 'utf8'
});
body = body.trim();
if (body[0] != '{') this.throw(400, 'request body must be a JSON object');
try {
this.body = JSON.parse(body);
} catch (err) {
err.status = 400;
throw err;
}
})
// only urlencoded requests
app.use(function *(next){
if (this.path !== '/urlencoded') return yield next;
if (this.length == 0) this.throw(400, 'no request body');
if (this.length == null) this.throw(411, 'content length required');
if (!this.is('application/x-www-form-urlencoded')) this.throw(415, 'urlencoded bodies only');
var body = yield rawBody(this.req, {
length: this.length,
limit: 25, // bytes
encoding: 'utf8'
});
try {
this.body = qs.parse(body);
} catch (err) {
err.status = 400;
throw err;
}
})
if ('POST' != this.method) return yield next;
var body = yield parse(this, { limit: '1kb' });
if (!body.name) this.throw(400, '.name required');
this.body = { name: body.name.toUpperCase() };
});
if (!module.parent) app.listen(3000);

View File

@ -2,95 +2,35 @@ var app = require('./app');
var request = require('supertest').agent(app.listen());
describe('Body Parsing', function(){
describe('/json', function(){
describe('when POSTing JSON', function(){
it('should return a JSON body', function(done){
describe('POST /uppercase', function(){
describe('with JSON', function(){
it('should work', function(done){
request
.post('/json')
.send({
message: 'hello'
})
.post('/uppercase')
.send({ name: 'tobi' })
.expect(200)
.expect(/"message": "hello"/, done);
.expect({ name: 'TOBI' }, done);
})
})
describe('when POSTing urlencoded', function(){
it('should 415', function(done){
describe('with urlencoded', function(){
it('should work', function(done){
request
.post('/json')
.send('message=hello')
.expect(415, done);
.post('/uppercase')
.send('name=tj')
.expect(200)
.expect({ name: 'TJ' }, done);
})
})
describe('when POSTing a JSON primitive', function(){
it('should 400', function(done){
request
.post('/json')
.send(JSON.stringify(null))
.set('Content-Type', 'application/json')
.expect(400, done);
})
})
describe('when POSTing with length > limit', function(){
describe('when length > limit', function(){
it('should 413', function(done){
request
.post('/json')
.send({
some_really_long_string: Math.random()
})
.send({ name: Array(5000).join('a') })
.expect(413, done);
})
})
describe('when POSTing an empty body', function(){
it('should 411', function(done){
request
.post('/json')
.expect(411, done);
})
})
})
describe('/urlencoded', function(){
describe('when POSTing urlencoded', function(){
it('should return a JSON body', function(done){
request
.post('/urlencoded')
.send('message=hello')
.expect(200)
.expect(/"message": "hello"/, done);
})
})
describe('when POSTing JSON', function(){
it('should 415', function(done){
request
.post('/urlencoded')
.send({
message: 'hello'
})
.expect(415, done);
})
})
describe('when POSTing with length > limit', function(){
it('should 413', function(done){
request
.post('/urlencoded')
.send('some_really_long_string=' + Math.random())
.expect(413, done);
})
})
describe('when POSTing an empty body', function(){
it('should 411', function(done){
request
.post('/urlencoded')
.expect(411, done);
})
})
})
})

View File

@ -11,7 +11,8 @@
"co-busboy": "cojs/busboy",
"save-to": "~1.0.0",
"raw-body": "~1.1.1",
"co-fs": "~1.1.1"
"co-fs": "~1.1.1",
"co-body": "0.0.1"
},
"devDependencies": {
"co": "*",