Remove is-type and replace with a helper function :)

This commit is contained in:
Jonatan Nilsson 2019-10-12 14:31:02 +00:00
parent 54aa155328
commit 5a9a3f0dc2
6 changed files with 67 additions and 65 deletions

View file

@ -1,10 +1,12 @@
const getMimetype = require('./getmimetype');
module.exports = function accepts(ctx, type, ask) {
module.exports = function accepts(ctx, type, ask, isReq = true) {
if (!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 quality = 9999; // Little bit of a hack :)
if (types) {
@ -27,27 +29,56 @@ module.exports = function accepts(ctx, type, ask) {
if (type === 'accept-encoding') {
types.push('identity');
}
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 (ask.length === 0) {
return can;
if (ask.length === 0 && can) {
return can || false;
}
// 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];
}
let parsed = ask.slice();
if (type === 'accept') {
if (type === 'accept' || type === 'content-type') {
for (let t = 0; t < parsed.length; t++) {
parsed[t] = getMimetype(parsed[t]) || parsed[t];
if (parsed[t].startsWith('*/')) {
parsed[t] = parsed[t].substr(2);
} else if (parsed[t].indexOf('/*') < 0) {
parsed[t] = getMimetype(parsed[t]) || parsed[t];
}
}
if (type === 'content-type') {
can = [can.split(';')[0]];
}
}
@ -56,8 +87,9 @@ module.exports = function accepts(ctx, type, ask) {
for (let i = 0; i < can.length; i++) {
for (let t = 0; t < parsed.length; t++) {
// Check if we allow root checking (application/*)
if (type === 'accept') {
let allowRoot = can[i].indexOf('/*') >= 0;
if (type === 'accept' || type === 'content-type') {
let allowRoot = can[i].indexOf('/*') >= 0
|| parsed[t].indexOf('/*') >= 0;
// Big if :)
if (can[i] === '*/*'
@ -66,6 +98,12 @@ module.exports = function accepts(ctx, type, ask) {
&& parsed[t].indexOf('/') >= 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];
}
} else {

View file

@ -6,6 +6,10 @@
*/
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 response = require('./response');
const compose = require('./compose');
@ -13,10 +17,6 @@ const isJSON = require('./isjson');
const context = require('./context');
const request = require('./request');
const statuses = require('./statuses');
const Emitter = require('events');
const util = require('util');
const Stream = require('stream');
const http = require('http');
/**
* Expose `Application` class.

View file

@ -8,11 +8,10 @@
const URL = require('url').URL;
const net = require('net');
const stringify = require('url').format;
const fastparse = require('./fastparse');
const qs = require('querystring');
const typeis = require('type-is');
const fresh = require('fresh');
const util = require('util');
const fastparse = require('./fastparse');
const accepts = require('./accepts');
const IP = Symbol('context#ip');
@ -473,40 +472,6 @@ module.exports = {
.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
* the best match when true, otherwise `false`, in which
@ -658,9 +623,9 @@ module.exports = {
*/
is(types) {
if (!types) return typeis(this.req);
if (!types) return accepts(this, 'content-type', []);
if (!Array.isArray(types)) types = [].slice.call(arguments);
return typeis(this.req, types);
return accepts(this, 'content-type', types);
},
/**

View file

@ -7,14 +7,14 @@
const ReadStream = require('fs').ReadStream;
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 extname = require('path').extname;
const getMimetype = require('./getmimetype');
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.
@ -287,6 +287,8 @@ module.exports = {
// html
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, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
@ -434,10 +436,9 @@ module.exports = {
*/
is(types) {
const type = this.type;
if (!types) return type || false;
if (!types) return this.type || false;
if (!Array.isArray(types)) types = [].slice.call(arguments);
return typeis(type, types);
return accepts(this, 'content-type', types, false);
},
/**

View file

@ -25,8 +25,7 @@
"content-disposition": "jharrilim/content-disposition#572383f",
"debug-ms": "~4.1.2",
"fresh": "~0.5.2",
"http-errors-lite": "^2.0.2",
"type-is": "^1.6.16"
"http-errors-lite": "^2.0.2"
},
"devDependencies": {
"egg-bin": "^4.13.0",

View file

@ -32,8 +32,7 @@ describe('app', () => {
ctx.socket.writable = false;
ctx.status = 204;
// throw if .writeHead or .end is called
ctx.res.writeHead =
ctx.res.end = () => {
ctx.res.writeHead = ctx.res.end = () => {
throw new Error('response sent');
};
});