req.is(): make better

closes #105 and #106
master
Jonathan Ong 2013-11-28 00:13:13 -08:00
parent 1b9960a28e
commit 8717a3ad2b
3 changed files with 122 additions and 52 deletions

View File

@ -152,26 +152,24 @@ this.body = yield db.find('something');
### req.is(type)
Check if the incoming request contains the `Content-Type`
header field, and it contains the give mime `type`.
Check if the incoming request contains the "Content-Type"
header field, and it contains any of the give mime `type`s.
If there is no request body, `null` is returned.
If there is no content type, `false` is returned.
Otherwise, it returns the first `type` that matches.
```js
// With Content-Type: text/html; charset=utf-8
this.is('html');
this.is('.html');
this.is('text/html');
this.is('text/*');
// => true
this.is('html'); // => 'html'
this.is('text/html'); // => 'text/html'
this.is('text/*', 'text/html'); // => 'text/*'
// When Content-Type is application/json
this.is('json');
this.is('.json');
this.is('application/json');
this.is('application/*');
// => true
this.is('json', 'urlencoded'); // => 'json'
this.is('application/json'); // => 'application/json'
this.is('html', 'application/*'); // => 'application/*'
this.is('html');
// => false
this.is('html'); // => false
```
### req.accepts(types)

View File

@ -487,49 +487,63 @@ module.exports = {
/**
* Check if the incoming request contains the "Content-Type"
* header field, and it contains the give mime `type`.
* header field, and it contains any of the give mime `type`s.
* If there is no request body, `null` is returned.
* If there is no content type, `false` is returned.
* Otherwise, it returns the first `type` that matches.
*
* Examples:
*
* // With Content-Type: text/html; charset=utf-8
* this.is('html');
* this.is('text/html');
* this.is('text/*');
* // => true
* this.is('html'); // => 'html'
* this.is('text/html'); // => 'text/html'
* this.is('text/*', 'text/html'); // => 'text/*'
*
* // When Content-Type is application/json
* this.is('json');
* this.is('application/json');
* this.is('application/*');
* // => true
* this.is('json', 'urlencoded'); // => 'json'
* this.is('application/json'); // => 'application/json'
* this.is('html', 'application/*'); // => 'application/*'
*
* this.is('html');
* // => false
* this.is('html'); // => false
*
* @param {String} type
* @return {Boolean}
* @param {String|Array} types...
* @return {String|false|null}
* @api public
*/
is: function(type){
is: function(types){
// no request body
if (!(this.length || 'transfer-encoding' in this.header)) return null;
var ct = this.type;
// request body without a content type?
if (!ct) return false;
ct = ct.split(';')[0];
// extension given
if (!~type.indexOf('/')) type = mime.lookup(type);
// type or subtype match
if (~type.indexOf('*')) {
type = type.split('/');
ct = ct.split('/');
if ('*' == type[0] && type[1] == ct[1]) return true;
if ('*' == type[1] && type[0] == ct[0]) return true;
return false;
if (!types) return ct;
if (!Array.isArray(types)) types = [].slice.call(arguments);
var type, mt, cts;
for (var i = 0; i < types.length; i++) {
type = types[i];
// exact match
if (type == ct) return type;
// convert to a valid mime type
switch (type) {
case 'urlencoded':
mt = 'application/x-www-form-urlencoded';
break;
default:
mt = ~type.indexOf('/') ? type : mime.lookup(type);
}
// mime types match
if (mt == ct) return type;
// type or subtype match
if (!~type.indexOf('*')) continue;
mt = mt.split('/');
cts = cts || ct.split('/');
if ('*' == mt[0] && mt[1] == cts[1]) return type;
if ('*' == mt[1] && mt[0] == cts[0]) return type;
}
// exact match
return type == ct;
// no matches
return false;
},
/**

View File

@ -1,38 +1,96 @@
var should = require('should');
var context = require('../context');
describe('ctx.is(type)', function(){
it('should ignore params', function(){
var ctx = context();
ctx.header['content-type'] = 'text/html; charset=utf-8';
ctx.is('text/*').should.be.true;
ctx.header['transfer-encoding'] = 'chunked';
ctx.is('text/*').should.equal('text/*');
})
describe('given a mime', function(){
it('should check the type', function(){
describe('when no body is given', function(){
it('should return null', function(){
var ctx = context();
should(ctx.is()).null;
should(ctx.is('image/*')).null;
should(ctx.is('text/*', 'image/*')).null;
})
})
describe('when no content type is given', function(){
it('should return false', function(){
var ctx = context();
ctx.header['transfer-encoding'] = 'chunked';
ctx.is().should.be.false;
ctx.is('image/*').should.be.false;
ctx.is('text/*', 'image/*').should.be.false;
})
})
describe('give no types', function(){
it('should return the mime type', function(){
var ctx = context();
ctx.header['content-type'] = 'image/png';
ctx.header['transfer-encoding'] = 'chunked';
ctx.is('image/png').should.be.true;
ctx.is('image/*').should.be.true;
ctx.is('*/png').should.be.true;
ctx.is().should.equal('image/png');
})
})
describe('given one type', function(){
it('should return the type or false', function(){
var ctx = context();
ctx.header['content-type'] = 'image/png';
ctx.header['transfer-encoding'] = 'chunked';
ctx.is('png').should.equal('png');
ctx.is('.png').should.equal('.png');
ctx.is('image/png').should.equal('image/png');
ctx.is('image/*').should.equal('image/*');
ctx.is('*/png').should.equal('*/png');
ctx.is('jpeg').should.be.false;
ctx.is('.jpeg').should.be.false;
ctx.is('image/jpeg').should.be.false;
ctx.is('text/*').should.be.false;
ctx.is('*/jpeg').should.be.false;
})
})
describe('given an extension', function(){
it('should check the type', function(){
describe('given multiple types', function(){
it('should return the first match or false', function(){
var ctx = context();
ctx.header['content-type'] = 'image/png';
ctx.header['transfer-encoding'] = 'chunked';
ctx.is('png').should.be.true;
ctx.is('.png').should.be.true;
ctx.is('png').should.equal('png');
ctx.is('.png').should.equal('.png');
ctx.is('text/*', 'image/*').should.equal('image/*');
ctx.is('image/*', 'text/*').should.equal('image/*');
ctx.is('image/*', 'image/png').should.equal('image/*');
ctx.is('image/png', 'image/*').should.equal('image/png');
ctx.is('jpeg').should.be.false;
ctx.is('.jpeg').should.be.false;
ctx.is('text/*', 'application/*').should.be.false;
ctx.is('text/html', 'text/plain', 'application/json').should.be.false;
})
})
describe('when Content-Type: application/x-www-form-urlencoded', function(){
it('should match `urlencoded', function(){
var ctx = context();
ctx.header['content-type'] = 'application/x-www-form-urlencoded';
ctx.header['transfer-encoding'] = 'chunked';
ctx.is('urlencoded').should.equal('urlencoded');
ctx.is('json', 'urlencoded').should.equal('urlencoded');
ctx.is('urlencoded', 'json').should.equal('urlencoded');
})
})
})