Add fast parse and remove parseurl
This commit is contained in:
parent
bd05c21456
commit
6b27b844ff
4 changed files with 112 additions and 6 deletions
57
lib/fastparse.js
Normal file
57
lib/fastparse.js
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
const url = require('url');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the `str` url with fast-path short-cut.
|
||||||
|
*
|
||||||
|
* @param {string} str
|
||||||
|
* @return {Object}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = function fastparse(str) {
|
||||||
|
if (typeof str !== 'string' || str.charCodeAt(0) !== 0x2f /* / */) {
|
||||||
|
return url.parse(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
let pathname = str;
|
||||||
|
let query = null;
|
||||||
|
let search = null;
|
||||||
|
|
||||||
|
// This takes the regexp from https://github.com/joyent/node/pull/7878
|
||||||
|
// Which is /^(\/[^?#\s]*)(\?[^#\s]*)?$/
|
||||||
|
// And unrolls it into a for loop
|
||||||
|
for (let i = 1; i < str.length; i++) {
|
||||||
|
switch (str.charCodeAt(i)) {
|
||||||
|
case 0x3f: /* ? */
|
||||||
|
if (search === null) {
|
||||||
|
pathname = str.substring(0, i);
|
||||||
|
query = str.substring(i + 1);
|
||||||
|
search = str.substring(i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x09: /* \t */
|
||||||
|
case 0x0a: /* \n */
|
||||||
|
case 0x0c: /* \f */
|
||||||
|
case 0x0d: /* \r */
|
||||||
|
case 0x20: /* */
|
||||||
|
case 0x23: /* # */
|
||||||
|
case 0xa0:
|
||||||
|
case 0xfeff:
|
||||||
|
return url.parse(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let parsed = new url.Url();
|
||||||
|
|
||||||
|
parsed.path = str;
|
||||||
|
parsed.href = str;
|
||||||
|
parsed.pathname = pathname;
|
||||||
|
|
||||||
|
if (search !== null) {
|
||||||
|
parsed.query = query;
|
||||||
|
parsed.search = search;
|
||||||
|
}
|
||||||
|
parsed.__raw = str;
|
||||||
|
|
||||||
|
return parsed;
|
||||||
|
};
|
|
@ -8,7 +8,7 @@
|
||||||
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 parse = require('parseurl');
|
const fastparse = require('./fastparse');
|
||||||
const qs = require('querystring');
|
const qs = require('querystring');
|
||||||
const typeis = require('type-is');
|
const typeis = require('type-is');
|
||||||
const fresh = require('fresh');
|
const fresh = require('fresh');
|
||||||
|
@ -139,7 +139,14 @@ module.exports = {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
get path() {
|
get path() {
|
||||||
return parse(this.req).pathname;
|
return this.urlParsed.pathname;
|
||||||
|
},
|
||||||
|
|
||||||
|
get urlParsed() {
|
||||||
|
if (!this.req.__url || this.req.__url.__raw !== this.req.url) {
|
||||||
|
this.req.__url = fastparse(this.req.url);
|
||||||
|
}
|
||||||
|
return this.req.__url;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -150,7 +157,7 @@ module.exports = {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
set path(path) {
|
set path(path) {
|
||||||
const url = parse(this.req);
|
const url = this.urlParsed;
|
||||||
if (url.pathname === path) return;
|
if (url.pathname === path) return;
|
||||||
|
|
||||||
url.pathname = path;
|
url.pathname = path;
|
||||||
|
@ -192,7 +199,7 @@ module.exports = {
|
||||||
|
|
||||||
get querystring() {
|
get querystring() {
|
||||||
if (!this.req) return '';
|
if (!this.req) return '';
|
||||||
return parse(this.req).query || '';
|
return this.urlParsed.query || '';
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -203,7 +210,7 @@ module.exports = {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
set querystring(str) {
|
set querystring(str) {
|
||||||
const url = parse(this.req);
|
const url = this.urlParsed;
|
||||||
if (url.search === `?${str}`) return;
|
if (url.search === `?${str}`) return;
|
||||||
|
|
||||||
url.search = str;
|
url.search = str;
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
"koa-compose": "^4.1.0",
|
"koa-compose": "^4.1.0",
|
||||||
"koa-is-json": "^1.0.0",
|
"koa-is-json": "^1.0.0",
|
||||||
"on-finished": "^2.3.0",
|
"on-finished": "^2.3.0",
|
||||||
"parseurl": "^1.3.2",
|
|
||||||
"type-is": "^1.6.16",
|
"type-is": "^1.6.16",
|
||||||
"vary": "^1.1.2"
|
"vary": "^1.1.2"
|
||||||
},
|
},
|
||||||
|
|
43
test/parseurl/fastparse.js
Normal file
43
test/parseurl/fastparse.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
const assert = require('assert');
|
||||||
|
const fastparse = require('../../lib/fastparse');
|
||||||
|
|
||||||
|
const URL_EMPTY_VALUE = null;
|
||||||
|
|
||||||
|
describe('fastparse(url)', () => {
|
||||||
|
it('should parse the requrst URL', () => {
|
||||||
|
let url = fastparse('/foo/bar');
|
||||||
|
assert.strictEqual(url.host, URL_EMPTY_VALUE);
|
||||||
|
assert.strictEqual(url.hostname, URL_EMPTY_VALUE);
|
||||||
|
assert.strictEqual(url.href, '/foo/bar');
|
||||||
|
assert.strictEqual(url.pathname, '/foo/bar');
|
||||||
|
assert.strictEqual(url.port, URL_EMPTY_VALUE);
|
||||||
|
assert.strictEqual(url.query, URL_EMPTY_VALUE);
|
||||||
|
assert.strictEqual(url.search, URL_EMPTY_VALUE);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should parse with query string', () => {
|
||||||
|
let url = fastparse('/foo/bar?fizz=buzz');
|
||||||
|
assert.strictEqual(url.host, URL_EMPTY_VALUE);
|
||||||
|
assert.strictEqual(url.hostname, URL_EMPTY_VALUE);
|
||||||
|
assert.strictEqual(url.href, '/foo/bar?fizz=buzz');
|
||||||
|
assert.strictEqual(url.pathname, '/foo/bar');
|
||||||
|
assert.strictEqual(url.port, URL_EMPTY_VALUE);
|
||||||
|
assert.strictEqual(url.query, 'fizz=buzz');
|
||||||
|
assert.strictEqual(url.search, '?fizz=buzz');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should parse a full URL', () => {
|
||||||
|
let url = fastparse('http://localhost:8888/foo/bar');
|
||||||
|
assert.strictEqual(url.host, 'localhost:8888');
|
||||||
|
assert.strictEqual(url.hostname, 'localhost');
|
||||||
|
assert.strictEqual(url.href, 'http://localhost:8888/foo/bar');
|
||||||
|
assert.strictEqual(url.pathname, '/foo/bar');
|
||||||
|
assert.strictEqual(url.port, '8888');
|
||||||
|
assert.strictEqual(url.query, URL_EMPTY_VALUE);
|
||||||
|
assert.strictEqual(url.search, URL_EMPTY_VALUE);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not choke on auth-looking URL', () => {
|
||||||
|
assert.strictEqual(fastparse('//todo@txt').pathname, '//todo@txt');
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in a new issue