url: significantly improve the performance of the url module
(landed by @rvagg) PR-URL: https://github.com/iojs/io.js/pull/1561 Reviewed-By: Domenic Denicola <domenic@domenicdenicola.com> Reviewed-By: Rod Vagg <rod@vagg.org>
This commit is contained in:
parent
57c4cc26e2
commit
3fd7fc429c
@ -20,7 +20,7 @@ function ClientRequest(options, cb) {
|
|||||||
OutgoingMessage.call(self);
|
OutgoingMessage.call(self);
|
||||||
|
|
||||||
if (typeof options === 'string') {
|
if (typeof options === 'string') {
|
||||||
options = url.parse(options);
|
options = url.parse(options).toJSON();
|
||||||
} else {
|
} else {
|
||||||
options = util._extend({}, options);
|
options = util._extend({}, options);
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ exports.Agent = Agent;
|
|||||||
|
|
||||||
exports.request = function(options, cb) {
|
exports.request = function(options, cb) {
|
||||||
if (typeof options === 'string') {
|
if (typeof options === 'string') {
|
||||||
options = url.parse(options);
|
options = url.parse(options).toJSON();
|
||||||
} else {
|
} else {
|
||||||
options = util._extend({}, options);
|
options = util._extend({}, options);
|
||||||
}
|
}
|
||||||
|
1618
lib/url.js
1618
lib/url.js
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
const uv = process.binding('uv');
|
const uv = process.binding('uv');
|
||||||
const Debug = require('vm').runInDebugContext('Debug');
|
const Debug = require('vm').runInDebugContext('Debug');
|
||||||
|
const Url = require('url').Url;
|
||||||
|
|
||||||
const formatRegExp = /%[sdj%]/g;
|
const formatRegExp = /%[sdj%]/g;
|
||||||
exports.format = function(f) {
|
exports.format = function(f) {
|
||||||
@ -743,6 +744,8 @@ exports.inherits = function(ctor, superCtor) {
|
|||||||
exports._extend = function(origin, add) {
|
exports._extend = function(origin, add) {
|
||||||
// Don't do anything if add isn't an object
|
// Don't do anything if add isn't an object
|
||||||
if (add === null || typeof add !== 'object') return origin;
|
if (add === null || typeof add !== 'object') return origin;
|
||||||
|
// For compatibility with Url objects
|
||||||
|
if (add instanceof Url) add = add.toJSON();
|
||||||
|
|
||||||
var keys = Object.keys(add);
|
var keys = Object.keys(add);
|
||||||
var i = keys.length;
|
var i = keys.length;
|
||||||
|
378
test/parallel/test-url-accessors.js
Normal file
378
test/parallel/test-url-accessors.js
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('../common');
|
||||||
|
const assert = require('assert');
|
||||||
|
const util = require('util');
|
||||||
|
const url = require('url');
|
||||||
|
|
||||||
|
// url: The url object to test (if string, it's parsed to url)
|
||||||
|
// set: Object where the fields are the property values to set in the url object
|
||||||
|
// test: Object where the fields are the property values to test in the url object
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// Tests that the host property reflects the new port that was set on the url object
|
||||||
|
// {
|
||||||
|
// url: 'http://www.google.com',
|
||||||
|
// set: {port: 443},
|
||||||
|
// test: {host: 'www.google.com:443'}
|
||||||
|
// }
|
||||||
|
|
||||||
|
const accessorTests = [{
|
||||||
|
// Setting href to null nullifies all properties.
|
||||||
|
url: 'http://user:password@www.google.com:80/path?query#hash',
|
||||||
|
set: {href: null},
|
||||||
|
test: {
|
||||||
|
protocol: null,
|
||||||
|
port: null,
|
||||||
|
query: null,
|
||||||
|
auth: null,
|
||||||
|
hostname: null,
|
||||||
|
host: null,
|
||||||
|
pathname: null,
|
||||||
|
hash: null,
|
||||||
|
search: null,
|
||||||
|
href: ''
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// Resetting href doesn't forget query string parsing preference
|
||||||
|
url: url.parse('http://www.google.com?key=value', true),
|
||||||
|
set: {href: 'http://www.yahoo.com?key2=value2'},
|
||||||
|
test: {
|
||||||
|
query: {key2: 'value2'}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// Setting href to non-null non-string coerces to string
|
||||||
|
url: 'google',
|
||||||
|
set: {href: undefined},
|
||||||
|
test: {
|
||||||
|
path: 'undefined',
|
||||||
|
href: 'undefined'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// Setting port is reflected in host
|
||||||
|
url: 'http://www.google.com',
|
||||||
|
set: {port: 443},
|
||||||
|
test: {
|
||||||
|
host: 'www.google.com:443',
|
||||||
|
hostname: 'www.google.com',
|
||||||
|
port: '443'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// Port is treated as an unsigned 16-bit integer
|
||||||
|
url: 'http://www.google.com',
|
||||||
|
set: {port: 100000},
|
||||||
|
test: {
|
||||||
|
host: 'www.google.com:34464',
|
||||||
|
hostname: 'www.google.com',
|
||||||
|
port: '34464'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// Port is parsed numerically
|
||||||
|
url: 'http://www.google.com',
|
||||||
|
set: {port: '100000'},
|
||||||
|
test: {
|
||||||
|
host: 'www.google.com:34464',
|
||||||
|
hostname: 'www.google.com',
|
||||||
|
port: '34464'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// Invalid port values become 0
|
||||||
|
url: 'http://www.google.com',
|
||||||
|
set: {port: NaN},
|
||||||
|
test: {
|
||||||
|
host: 'www.google.com:0',
|
||||||
|
hostname: 'www.google.com',
|
||||||
|
port: '0'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// Auth special characters are urlencoded
|
||||||
|
url: 'http://www.google.com',
|
||||||
|
set: {auth: 'weird@'},
|
||||||
|
test: {
|
||||||
|
auth: 'weird@',
|
||||||
|
href: 'http://weird%40@www.google.com/'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// Auth password separator is not urlencoded
|
||||||
|
url: 'http://www.google.com',
|
||||||
|
set: {auth: 'weird@:password:'},
|
||||||
|
test: {
|
||||||
|
auth: 'weird@:password:',
|
||||||
|
href: 'http://weird%40:password%3A@www.google.com/'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
|
||||||
|
// Host is reflected in hostname and port
|
||||||
|
url: 'http://www.google.com',
|
||||||
|
set: {host: 'www.yahoo.com:443'},
|
||||||
|
test: {
|
||||||
|
hostname: 'www.yahoo.com',
|
||||||
|
host: 'www.yahoo.com:443',
|
||||||
|
port: '443',
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
|
||||||
|
// Port in host has port setter behavior
|
||||||
|
url: 'http://www.google.com',
|
||||||
|
set: {host: 'www.yahoo.com:100000'},
|
||||||
|
test: {
|
||||||
|
hostname: 'www.yahoo.com',
|
||||||
|
host: 'www.yahoo.com:34464',
|
||||||
|
port: '34464',
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
|
||||||
|
// Hostname in host has hostname setter behavior
|
||||||
|
url: 'http://www.google.com',
|
||||||
|
set: {host: 'www.yahoo .com'},
|
||||||
|
test: {
|
||||||
|
hostname: 'www.yahoo%20.com',
|
||||||
|
host: 'www.yahoo%20.com',
|
||||||
|
port: null,
|
||||||
|
href: 'http://www.yahoo%20.com/'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
|
||||||
|
// Nullifying host nullifies port and hostname
|
||||||
|
url: 'http://www.google.com:443',
|
||||||
|
set: {host: null},
|
||||||
|
test: {
|
||||||
|
hostname: null,
|
||||||
|
host: null,
|
||||||
|
port: null
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
|
||||||
|
// Question mark is added to search
|
||||||
|
url: 'http://www.google.com',
|
||||||
|
set: {search: 'key=value'},
|
||||||
|
test: {
|
||||||
|
search: '?key=value'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
|
||||||
|
// It's impossible to start a hash in search
|
||||||
|
url: 'http://www.google.com',
|
||||||
|
set: {search: 'key=value#hash'},
|
||||||
|
test: {
|
||||||
|
search: '?key=value%23hash'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
|
||||||
|
// Query is reflected in urls that parse query strings
|
||||||
|
url: url.parse('http://www.google.com', true),
|
||||||
|
set: {search: 'key=value'},
|
||||||
|
test: {
|
||||||
|
search: '?key=value',
|
||||||
|
query: {key: 'value'}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
|
||||||
|
// Search is reflected in path
|
||||||
|
url: 'http://www.google.com',
|
||||||
|
set: {search: 'key=value'},
|
||||||
|
test: {
|
||||||
|
path: '/?key=value'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
|
||||||
|
// Empty search is ok
|
||||||
|
url: 'http://www.google.com',
|
||||||
|
set: {search: ''},
|
||||||
|
test: {
|
||||||
|
search: '?',
|
||||||
|
path: '/?'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
|
||||||
|
// Nullifying search is ok
|
||||||
|
url: 'http://www.google.com?key=value',
|
||||||
|
set: {search: null},
|
||||||
|
test: {
|
||||||
|
search: null,
|
||||||
|
path: '/'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
|
||||||
|
// # is added to hash if it's missing
|
||||||
|
url: 'http://www.google.com',
|
||||||
|
set: {hash: 'myhash'},
|
||||||
|
test: {
|
||||||
|
hash: '#myhash'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
|
||||||
|
// Empty hash is ok
|
||||||
|
url: 'http://www.google.com',
|
||||||
|
set: {hash: ''},
|
||||||
|
test: {
|
||||||
|
hash: '#'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
|
||||||
|
// Nullifying hash is ok
|
||||||
|
url: 'http://www.google.com#hash',
|
||||||
|
set: {hash: null},
|
||||||
|
test: {
|
||||||
|
hash: null
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
|
||||||
|
// / is added to pathname
|
||||||
|
url: 'http://www.google.com',
|
||||||
|
set: {pathname: 'path'},
|
||||||
|
test: {
|
||||||
|
pathname: '/path'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
|
||||||
|
// It's impossible to start query in pathname
|
||||||
|
url: 'http://www.google.com',
|
||||||
|
set: {pathname: 'path?key=value'},
|
||||||
|
test: {
|
||||||
|
pathname: '/path%3Fkey=value'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
|
||||||
|
// It's impossible to start hash in pathname
|
||||||
|
url: 'http://www.google.com',
|
||||||
|
set: {pathname: 'path#hash'},
|
||||||
|
test: {
|
||||||
|
pathname: '/path%23hash'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// Backslashes are treated as slashes in pathnames
|
||||||
|
url: 'http://www.google.com',
|
||||||
|
set: {pathname: '\\path\\name'},
|
||||||
|
test: {
|
||||||
|
pathname: '/path/name'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// Empty path is ok
|
||||||
|
url: 'http://www.google.com',
|
||||||
|
set: {pathname: ''},
|
||||||
|
test: {
|
||||||
|
pathname: '/'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// Null path is ok
|
||||||
|
url: 'http://www.google.com/path',
|
||||||
|
set: {pathname: null},
|
||||||
|
test: {
|
||||||
|
pathname: null
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// Pathname is reflected in path
|
||||||
|
url: 'http://www.google.com/path',
|
||||||
|
set: {pathname: '/path2'},
|
||||||
|
test: {
|
||||||
|
path: '/path2'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// Protocol doesn't require colon
|
||||||
|
url: 'http://www.google.com/path',
|
||||||
|
set: {protocol: 'mailto'},
|
||||||
|
test: {
|
||||||
|
protocol: 'mailto:'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// Invalid protocol doesn't change protocol
|
||||||
|
url: 'http://www.google.com/path',
|
||||||
|
set: {protocol: 'mailto '},
|
||||||
|
test: {
|
||||||
|
protocol: 'http:'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// Nullifying protocol is ok
|
||||||
|
url: 'http://www.google.com/path',
|
||||||
|
set: {protocol: null},
|
||||||
|
test: {
|
||||||
|
protocol: null
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// Empty protocol is invalid
|
||||||
|
url: 'http://www.google.com/path',
|
||||||
|
set: {protocol: ''},
|
||||||
|
test: {
|
||||||
|
protocol: 'http:'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// Set query to an object
|
||||||
|
url: 'http://www.google.com/path',
|
||||||
|
set: {query: {key: 'value'}},
|
||||||
|
test: {
|
||||||
|
search: '?key=value',
|
||||||
|
href: 'http://www.google.com/path?key=value'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// Set query to null is ok
|
||||||
|
url: 'http://www.google.com/path?key=value',
|
||||||
|
set: {query: null},
|
||||||
|
test: {
|
||||||
|
search: null,
|
||||||
|
query: null,
|
||||||
|
href: 'http://www.google.com/path'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// path is reflected in search and pathname
|
||||||
|
url: 'http://www.google.com/path?key=value',
|
||||||
|
set: {path: 'path2?key2=value2'},
|
||||||
|
test: {
|
||||||
|
pathname: '/path2',
|
||||||
|
search: '?key2=value2',
|
||||||
|
href: 'http://www.google.com/path2?key2=value2'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// path is reflected in search and pathname 2
|
||||||
|
url: 'http://www.google.com/path?key=value',
|
||||||
|
set: {path: '?key2=value2'},
|
||||||
|
test: {
|
||||||
|
pathname: '/',
|
||||||
|
search: '?key2=value2',
|
||||||
|
href: 'http://www.google.com/?key2=value2'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// path is reflected in search and pathname 3
|
||||||
|
url: 'http://www.google.com/path?key=value',
|
||||||
|
set: {path: 'path2'},
|
||||||
|
test: {
|
||||||
|
pathname: '/path2',
|
||||||
|
search: null,
|
||||||
|
href: 'http://www.google.com/path2'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// path is reflected in search and pathname 4
|
||||||
|
url: 'http://www.google.com/path?key=value',
|
||||||
|
set: {path: null},
|
||||||
|
test: {
|
||||||
|
pathname: null,
|
||||||
|
search: null,
|
||||||
|
href: 'http://www.google.com'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
accessorTests.forEach(function(test) {
|
||||||
|
var urlObject = test.url;
|
||||||
|
|
||||||
|
if (typeof urlObject === 'string')
|
||||||
|
urlObject = url.parse(urlObject);
|
||||||
|
|
||||||
|
Object.keys(test.set).forEach(function(key) {
|
||||||
|
urlObject[key] = test.set[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.keys(test.test).forEach(function(key) {
|
||||||
|
const actual = urlObject[key];
|
||||||
|
const expected = test.test[key];
|
||||||
|
|
||||||
|
const message = `Expecting ${key}=${util.inspect(expected)} ` +
|
||||||
|
`but got ${key}=${util.inspect(actual)}. ` +
|
||||||
|
`URL object: ${JSON.stringify(urlObject, null, 2)} ` +
|
||||||
|
`\nTest object: ${JSON.stringify(test, null, 2)}`
|
||||||
|
|
||||||
|
assert.deepStrictEqual(actual, expected, message);
|
||||||
|
});
|
||||||
|
});
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user