Remove is-type and replace with a helper function :)
This commit is contained in:
parent
54aa155328
commit
5a9a3f0dc2
6 changed files with 67 additions and 65 deletions
|
@ -1,10 +1,12 @@
|
||||||
const getMimetype = require('./getmimetype');
|
const getMimetype = require('./getmimetype');
|
||||||
|
|
||||||
module.exports = function accepts(ctx, type, ask) {
|
module.exports = function accepts(ctx, type, ask, isReq = true) {
|
||||||
if (!ctx._accept) {
|
if (!ctx._accept) {
|
||||||
ctx._accept = {};
|
ctx._accept = {};
|
||||||
}
|
}
|
||||||
if (!ctx._accept[type]) {
|
|
||||||
|
// We don't need to parse content-type
|
||||||
|
if (!ctx._accept[type] && type !== 'content-type') {
|
||||||
let types = ctx.req.headers[type];
|
let types = ctx.req.headers[type];
|
||||||
let quality = 9999; // Little bit of a hack :)
|
let quality = 9999; // Little bit of a hack :)
|
||||||
if (types) {
|
if (types) {
|
||||||
|
@ -27,37 +29,67 @@ module.exports = function accepts(ctx, type, ask) {
|
||||||
if (type === 'accept-encoding') {
|
if (type === 'accept-encoding') {
|
||||||
types.push('identity');
|
types.push('identity');
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx._accept[type] = types;
|
ctx._accept[type] = types;
|
||||||
}
|
}
|
||||||
|
|
||||||
let can = ctx._accept[type];
|
let can;
|
||||||
|
|
||||||
|
if (type === 'content-type') {
|
||||||
|
if (isReq) {
|
||||||
|
// Check if a request has a request body.
|
||||||
|
// A request with a body __must__ either have `transfer-encoding`
|
||||||
|
// or `content-length` headers set.
|
||||||
|
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3
|
||||||
|
if (ctx.req.headers['transfer-encoding'] === undefined
|
||||||
|
&& isNaN(ctx.req.headers['content-length'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
can = ctx.req.headers[type];
|
||||||
|
} else {
|
||||||
|
can = ctx.type;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
can = ctx._accept[type];
|
||||||
|
if (!can.length) can = null;
|
||||||
|
}
|
||||||
|
|
||||||
// If empty argument, return all supported can
|
// If empty argument, return all supported can
|
||||||
if (ask.length === 0) {
|
if (ask.length === 0 && can) {
|
||||||
return can;
|
return can || false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no supported was sent, return the first ask item
|
// If no supported was sent, return the first ask item
|
||||||
if (!can.length) {
|
// unless we're dealing with content-type we need to be smarter.
|
||||||
|
if (!can) {
|
||||||
|
if (type === 'content-type') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return ask[0];
|
return ask[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
let parsed = ask.slice();
|
let parsed = ask.slice();
|
||||||
|
|
||||||
if (type === 'accept') {
|
if (type === 'accept' || type === 'content-type') {
|
||||||
for (let t = 0; t < parsed.length; t++) {
|
for (let t = 0; t < parsed.length; t++) {
|
||||||
|
if (parsed[t].startsWith('*/')) {
|
||||||
|
parsed[t] = parsed[t].substr(2);
|
||||||
|
} else if (parsed[t].indexOf('/*') < 0) {
|
||||||
parsed[t] = getMimetype(parsed[t]) || parsed[t];
|
parsed[t] = getMimetype(parsed[t]) || parsed[t];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (type === 'content-type') {
|
||||||
|
can = [can.split(';')[0]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Loop over the supported can, returning the first
|
// Loop over the supported can, returning the first
|
||||||
// matching ask type.
|
// matching ask type.
|
||||||
for (let i = 0; i < can.length; i++) {
|
for (let i = 0; i < can.length; i++) {
|
||||||
for (let t = 0; t < parsed.length; t++) {
|
for (let t = 0; t < parsed.length; t++) {
|
||||||
// Check if we allow root checking (application/*)
|
// Check if we allow root checking (application/*)
|
||||||
if (type === 'accept') {
|
if (type === 'accept' || type === 'content-type') {
|
||||||
let allowRoot = can[i].indexOf('/*') >= 0;
|
let allowRoot = can[i].indexOf('/*') >= 0
|
||||||
|
|| parsed[t].indexOf('/*') >= 0;
|
||||||
|
|
||||||
// Big if :)
|
// Big if :)
|
||||||
if (can[i] === '*/*'
|
if (can[i] === '*/*'
|
||||||
|
@ -66,6 +98,12 @@ module.exports = function accepts(ctx, type, ask) {
|
||||||
&& parsed[t].indexOf('/') >= 0
|
&& parsed[t].indexOf('/') >= 0
|
||||||
&& can[i].split('/')[0] === parsed[t].split('/')[0]
|
&& can[i].split('/')[0] === parsed[t].split('/')[0]
|
||||||
)) {
|
)) {
|
||||||
|
if (type === 'content-type') {
|
||||||
|
if (ask[t].indexOf('/') === -1) {
|
||||||
|
return ask[t];
|
||||||
|
}
|
||||||
|
return can[i];
|
||||||
|
}
|
||||||
return ask[t];
|
return ask[t];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const debug = require('debug-ms')('koa:application');
|
const debug = require('debug-ms')('koa:application');
|
||||||
|
const Emitter = require('events');
|
||||||
|
const util = require('util');
|
||||||
|
const Stream = require('stream');
|
||||||
|
const http = require('http');
|
||||||
const onFinished = require('./onfinish');
|
const onFinished = require('./onfinish');
|
||||||
const response = require('./response');
|
const response = require('./response');
|
||||||
const compose = require('./compose');
|
const compose = require('./compose');
|
||||||
|
@ -13,10 +17,6 @@ const isJSON = require('./isjson');
|
||||||
const context = require('./context');
|
const context = require('./context');
|
||||||
const request = require('./request');
|
const request = require('./request');
|
||||||
const statuses = require('./statuses');
|
const statuses = require('./statuses');
|
||||||
const Emitter = require('events');
|
|
||||||
const util = require('util');
|
|
||||||
const Stream = require('stream');
|
|
||||||
const http = require('http');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expose `Application` class.
|
* Expose `Application` class.
|
||||||
|
|
|
@ -8,11 +8,10 @@
|
||||||
const URL = require('url').URL;
|
const URL = require('url').URL;
|
||||||
const net = require('net');
|
const net = require('net');
|
||||||
const stringify = require('url').format;
|
const stringify = require('url').format;
|
||||||
const fastparse = require('./fastparse');
|
|
||||||
const qs = require('querystring');
|
const qs = require('querystring');
|
||||||
const typeis = require('type-is');
|
|
||||||
const fresh = require('fresh');
|
const fresh = require('fresh');
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
|
const fastparse = require('./fastparse');
|
||||||
const accepts = require('./accepts');
|
const accepts = require('./accepts');
|
||||||
|
|
||||||
const IP = Symbol('context#ip');
|
const IP = Symbol('context#ip');
|
||||||
|
@ -473,40 +472,6 @@ module.exports = {
|
||||||
.slice(offset);
|
.slice(offset);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Get accept object.
|
|
||||||
* Lazily memoized.
|
|
||||||
*
|
|
||||||
* @return {Object}
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
accept(type, ) {
|
|
||||||
if (!this._accept) {
|
|
||||||
let types = this.req.headers.accept;
|
|
||||||
if (types) {
|
|
||||||
types = types.split(',')
|
|
||||||
.map(x => {
|
|
||||||
x = x.trim();
|
|
||||||
let q = 1;
|
|
||||||
if (x.indexOf('q=') >= 0) {
|
|
||||||
q = parseFloat(x.substr(x.indexOf('q=') + 2)) || 1;
|
|
||||||
x = x.substr(0, x.indexOf(';'));
|
|
||||||
}
|
|
||||||
return [x, q];
|
|
||||||
})
|
|
||||||
.sort((a, b) => b[1] - a[1])
|
|
||||||
.map(x => x[0]);
|
|
||||||
} else {
|
|
||||||
types = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
this._accept = {
|
|
||||||
types: types
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return this._accept;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the given `type(s)` is acceptable, returning
|
* Check if the given `type(s)` is acceptable, returning
|
||||||
* the best match when true, otherwise `false`, in which
|
* the best match when true, otherwise `false`, in which
|
||||||
|
@ -658,9 +623,9 @@ module.exports = {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
is(types) {
|
is(types) {
|
||||||
if (!types) return typeis(this.req);
|
if (!types) return accepts(this, 'content-type', []);
|
||||||
if (!Array.isArray(types)) types = [].slice.call(arguments);
|
if (!Array.isArray(types)) types = [].slice.call(arguments);
|
||||||
return typeis(this.req, types);
|
return accepts(this, 'content-type', types);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -7,14 +7,14 @@
|
||||||
|
|
||||||
const ReadStream = require('fs').ReadStream;
|
const ReadStream = require('fs').ReadStream;
|
||||||
const contentDisposition = require('content-disposition');
|
const contentDisposition = require('content-disposition');
|
||||||
const onFinish = require('./onfinish');
|
|
||||||
const isJSON = require('./isjson');
|
|
||||||
const typeis = require('type-is').is;
|
|
||||||
const statuses = require('./statuses');
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const extname = require('path').extname;
|
const extname = require('path').extname;
|
||||||
const getMimetype = require('./getmimetype');
|
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
|
const onFinish = require('./onfinish');
|
||||||
|
const isJSON = require('./isjson');
|
||||||
|
const statuses = require('./statuses');
|
||||||
|
const getMimetype = require('./getmimetype');
|
||||||
|
const accepts = require('./accepts');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prototype.
|
* Prototype.
|
||||||
|
@ -287,6 +287,8 @@ module.exports = {
|
||||||
|
|
||||||
// html
|
// html
|
||||||
if (this.ctx.headers.accept && this.ctx.headers.accept.indexOf('html') >= 0) {
|
if (this.ctx.headers.accept && this.ctx.headers.accept.indexOf('html') >= 0) {
|
||||||
|
// Sanitize the url in case developer does something silly like:
|
||||||
|
// ctx.redirect(ctx.query.goto) or something without sanitizing himself.
|
||||||
url = url.replace(/&/g, '&')
|
url = url.replace(/&/g, '&')
|
||||||
.replace(/</g, '<')
|
.replace(/</g, '<')
|
||||||
.replace(/>/g, '>')
|
.replace(/>/g, '>')
|
||||||
|
@ -434,10 +436,9 @@ module.exports = {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
is(types) {
|
is(types) {
|
||||||
const type = this.type;
|
if (!types) return this.type || false;
|
||||||
if (!types) return type || false;
|
|
||||||
if (!Array.isArray(types)) types = [].slice.call(arguments);
|
if (!Array.isArray(types)) types = [].slice.call(arguments);
|
||||||
return typeis(type, types);
|
return accepts(this, 'content-type', types, false);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -25,8 +25,7 @@
|
||||||
"content-disposition": "jharrilim/content-disposition#572383f",
|
"content-disposition": "jharrilim/content-disposition#572383f",
|
||||||
"debug-ms": "~4.1.2",
|
"debug-ms": "~4.1.2",
|
||||||
"fresh": "~0.5.2",
|
"fresh": "~0.5.2",
|
||||||
"http-errors-lite": "^2.0.2",
|
"http-errors-lite": "^2.0.2"
|
||||||
"type-is": "^1.6.16"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"egg-bin": "^4.13.0",
|
"egg-bin": "^4.13.0",
|
||||||
|
|
|
@ -32,8 +32,7 @@ describe('app', () => {
|
||||||
ctx.socket.writable = false;
|
ctx.socket.writable = false;
|
||||||
ctx.status = 204;
|
ctx.status = 204;
|
||||||
// throw if .writeHead or .end is called
|
// throw if .writeHead or .end is called
|
||||||
ctx.res.writeHead =
|
ctx.res.writeHead = ctx.res.end = () => {
|
||||||
ctx.res.end = () => {
|
|
||||||
throw new Error('response sent');
|
throw new Error('response sent');
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue