diff --git a/negotiation/app.js b/negotiation/app.js new file mode 100644 index 0000000..54879a1 --- /dev/null +++ b/negotiation/app.js @@ -0,0 +1,82 @@ + +var koa = require('koa'); +var app = module.exports = koa(); + +var tobi = { + _id: '123', + name: 'tobi', + species: 'ferret' +}; + +var loki = { + _id: '321', + name: 'loki', + species: 'ferret' +}; + +var users = { + tobi: tobi, + loki: loki +}; + +// content negotiation middleware. +// note that you should always check for +// presence of a body, and sometimes you +// may want to check the type, as it may +// be a stream, buffer, string, etc. + +app.use(function *(next){ + yield next; + + // responses vary on accepted type + this.vary('Accept'); + this.status = 'bad request'; + + // no body? nothing to format, early return + if (!this.body) return; + + // accepts json, koa handles this for us, + // so just return + if (this.accepts('json')) return; + + // accepts xml + if (this.accepts('xml')) { + this.type = 'xml'; + this.body = '' + this.body.name + ''; + return; + } + + // accepts html + if (this.accepts('html')) { + this.type = 'html'; + this.body = '

' + this.body.name + '

'; + return; + } + + // default to text + this.type = 'text'; + this.body = this.body.name; +}); + +// filter responses, in this case remove ._id +// since it's private + +app.use(function *(next){ + yield next; + + if (!this.body) return; + + delete this.body._id; +}); + +// try $ GET /tobi +// try $ GET /loki + +app.use(function *(){ + var name = this.path.slice(1); + var user = users[name]; + this.body = user; +}); + +if (!module.parent) app.listen(3000); + diff --git a/negotiation/test.js b/negotiation/test.js new file mode 100644 index 0000000..62fea8f --- /dev/null +++ b/negotiation/test.js @@ -0,0 +1,49 @@ +var app = require('./app'); +var request = require('supertest').agent(app.listen()); + +describe('negotiation', function() { + describe('json', function() { + it('should respond with json', function(done) { + request + .get('/tobi') + .set('Accept', 'application/json') + .expect(400) + .expect('vary', 'Accept') + .expect('Content-Type', /json/) + .expect({ name: 'tobi', species: 'ferret' }, done); + }); + }); + + describe('xml', function() { + it('should respond with xml', function(done) { + request + .get('/tobi') + .set('Accept', 'application/xml') + .expect(400) + .expect('Content-Type', /xml/) + .expect('tobi', done); + }); + }); + + describe('html', function() { + it('should respond with html', function(done) { + request + .get('/tobi') + .set('Accept', 'text/html') + .expect(400) + .expect('Content-Type', /html/) + .expect('

tobi

', done); + }); + }); + + describe('text', function() { + it('should respond with html', function(done) { + request + .get('/tobi') + .set('Accept', 'text/plaino') + .expect(400) + .expect('Content-Type', /plain/) + .expect('tobi', done); + }); + }); +});