update
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
# parseurl
|
||||
|
||||
[![NPM Version][npm-version-image]][npm-url]
|
||||
[![NPM Downloads][npm-downloads-image]][npm-url]
|
||||
[![Node.js Version][node-image]][node-url]
|
||||
[![Build Status][travis-image]][travis-url]
|
||||
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||
|
||||
Parse a URL with memoization.
|
||||
|
||||
## Install
|
||||
|
||||
This is a [Node.js](https://nodejs.org/en/) module available through the
|
||||
[npm registry](https://www.npmjs.com/). Installation is done using the
|
||||
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
|
||||
|
||||
```sh
|
||||
$ npm install parseurl
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
```js
|
||||
var parseurl = require('parseurl')
|
||||
```
|
||||
|
||||
### parseurl(req)
|
||||
|
||||
Parse the URL of the given request object (looks at the `req.url` property)
|
||||
and return the result. The result is the same as `url.parse` in Node.js core.
|
||||
Calling this function multiple times on the same `req` where `req.url` does
|
||||
not change will return a cached parsed object, rather than parsing again.
|
||||
|
||||
### parseurl.original(req)
|
||||
|
||||
Parse the original URL of the given request object and return the result.
|
||||
This works by trying to parse `req.originalUrl` if it is a string, otherwise
|
||||
parses `req.url`. The result is the same as `url.parse` in Node.js core.
|
||||
Calling this function multiple times on the same `req` where `req.originalUrl`
|
||||
does not change will return a cached parsed object, rather than parsing again.
|
||||
|
||||
## Benchmark
|
||||
|
||||
```bash
|
||||
$ npm run-script bench
|
||||
|
||||
> parseurl@1.3.3 bench nodejs-parseurl
|
||||
> node benchmark/index.js
|
||||
|
||||
http_parser@2.8.0
|
||||
node@10.6.0
|
||||
v8@6.7.288.46-node.13
|
||||
uv@1.21.0
|
||||
zlib@1.2.11
|
||||
ares@1.14.0
|
||||
modules@64
|
||||
nghttp2@1.32.0
|
||||
napi@3
|
||||
openssl@1.1.0h
|
||||
icu@61.1
|
||||
unicode@10.0
|
||||
cldr@33.0
|
||||
tz@2018c
|
||||
|
||||
> node benchmark/fullurl.js
|
||||
|
||||
Parsing URL "http://localhost:8888/foo/bar?user=tj&pet=fluffy"
|
||||
|
||||
4 tests completed.
|
||||
|
||||
fasturl x 2,207,842 ops/sec ±3.76% (184 runs sampled)
|
||||
nativeurl - legacy x 507,180 ops/sec ±0.82% (191 runs sampled)
|
||||
nativeurl - whatwg x 290,044 ops/sec ±1.96% (189 runs sampled)
|
||||
parseurl x 488,907 ops/sec ±2.13% (192 runs sampled)
|
||||
|
||||
> node benchmark/pathquery.js
|
||||
|
||||
Parsing URL "/foo/bar?user=tj&pet=fluffy"
|
||||
|
||||
4 tests completed.
|
||||
|
||||
fasturl x 3,812,564 ops/sec ±3.15% (188 runs sampled)
|
||||
nativeurl - legacy x 2,651,631 ops/sec ±1.68% (189 runs sampled)
|
||||
nativeurl - whatwg x 161,837 ops/sec ±2.26% (189 runs sampled)
|
||||
parseurl x 4,166,338 ops/sec ±2.23% (184 runs sampled)
|
||||
|
||||
> node benchmark/samerequest.js
|
||||
|
||||
Parsing URL "/foo/bar?user=tj&pet=fluffy" on same request object
|
||||
|
||||
4 tests completed.
|
||||
|
||||
fasturl x 3,821,651 ops/sec ±2.42% (185 runs sampled)
|
||||
nativeurl - legacy x 2,651,162 ops/sec ±1.90% (187 runs sampled)
|
||||
nativeurl - whatwg x 175,166 ops/sec ±1.44% (188 runs sampled)
|
||||
parseurl x 14,912,606 ops/sec ±3.59% (183 runs sampled)
|
||||
|
||||
> node benchmark/simplepath.js
|
||||
|
||||
Parsing URL "/foo/bar"
|
||||
|
||||
4 tests completed.
|
||||
|
||||
fasturl x 12,421,765 ops/sec ±2.04% (191 runs sampled)
|
||||
nativeurl - legacy x 7,546,036 ops/sec ±1.41% (188 runs sampled)
|
||||
nativeurl - whatwg x 198,843 ops/sec ±1.83% (189 runs sampled)
|
||||
parseurl x 24,244,006 ops/sec ±0.51% (194 runs sampled)
|
||||
|
||||
> node benchmark/slash.js
|
||||
|
||||
Parsing URL "/"
|
||||
|
||||
4 tests completed.
|
||||
|
||||
fasturl x 17,159,456 ops/sec ±3.25% (188 runs sampled)
|
||||
nativeurl - legacy x 11,635,097 ops/sec ±3.79% (184 runs sampled)
|
||||
nativeurl - whatwg x 240,693 ops/sec ±0.83% (189 runs sampled)
|
||||
parseurl x 42,279,067 ops/sec ±0.55% (190 runs sampled)
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
[coveralls-image]: https://badgen.net/coveralls/c/github/pillarjs/parseurl/master
|
||||
[coveralls-url]: https://coveralls.io/r/pillarjs/parseurl?branch=master
|
||||
[node-image]: https://badgen.net/npm/node/parseurl
|
||||
[node-url]: https://nodejs.org/en/download
|
||||
[npm-downloads-image]: https://badgen.net/npm/dm/parseurl
|
||||
[npm-url]: https://npmjs.org/package/parseurl
|
||||
[npm-version-image]: https://badgen.net/npm/v/parseurl
|
||||
[travis-image]: https://badgen.net/travis/pillarjs/parseurl/master
|
||||
[travis-url]: https://travis-ci.org/pillarjs/parseurl
|
||||
@@ -0,0 +1,327 @@
|
||||
/*!
|
||||
* proxy-addr
|
||||
* Copyright(c) 2014-2016 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
module.exports = proxyaddr
|
||||
module.exports.all = alladdrs
|
||||
module.exports.compile = compile
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var forwarded = require('forwarded')
|
||||
var ipaddr = require('ipaddr.js')
|
||||
|
||||
/**
|
||||
* Variables.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var DIGIT_REGEXP = /^[0-9]+$/
|
||||
var isip = ipaddr.isValid
|
||||
var parseip = ipaddr.parse
|
||||
|
||||
/**
|
||||
* Pre-defined IP ranges.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var IP_RANGES = {
|
||||
linklocal: ['169.254.0.0/16', 'fe80::/10'],
|
||||
loopback: ['127.0.0.1/8', '::1/128'],
|
||||
uniquelocal: ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', 'fc00::/7']
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all addresses in the request, optionally stopping
|
||||
* at the first untrusted.
|
||||
*
|
||||
* @param {Object} request
|
||||
* @param {Function|Array|String} [trust]
|
||||
* @public
|
||||
*/
|
||||
|
||||
function alladdrs (req, trust) {
|
||||
// get addresses
|
||||
var addrs = forwarded(req)
|
||||
|
||||
if (!trust) {
|
||||
// Return all addresses
|
||||
return addrs
|
||||
}
|
||||
|
||||
if (typeof trust !== 'function') {
|
||||
trust = compile(trust)
|
||||
}
|
||||
|
||||
for (var i = 0; i < addrs.length - 1; i++) {
|
||||
if (trust(addrs[i], i)) continue
|
||||
|
||||
addrs.length = i + 1
|
||||
}
|
||||
|
||||
return addrs
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile argument into trust function.
|
||||
*
|
||||
* @param {Array|String} val
|
||||
* @private
|
||||
*/
|
||||
|
||||
function compile (val) {
|
||||
if (!val) {
|
||||
throw new TypeError('argument is required')
|
||||
}
|
||||
|
||||
var trust
|
||||
|
||||
if (typeof val === 'string') {
|
||||
trust = [val]
|
||||
} else if (Array.isArray(val)) {
|
||||
trust = val.slice()
|
||||
} else {
|
||||
throw new TypeError('unsupported trust argument')
|
||||
}
|
||||
|
||||
for (var i = 0; i < trust.length; i++) {
|
||||
val = trust[i]
|
||||
|
||||
if (!Object.prototype.hasOwnProperty.call(IP_RANGES, val)) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Splice in pre-defined range
|
||||
val = IP_RANGES[val]
|
||||
trust.splice.apply(trust, [i, 1].concat(val))
|
||||
i += val.length - 1
|
||||
}
|
||||
|
||||
return compileTrust(compileRangeSubnets(trust))
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile `arr` elements into range subnets.
|
||||
*
|
||||
* @param {Array} arr
|
||||
* @private
|
||||
*/
|
||||
|
||||
function compileRangeSubnets (arr) {
|
||||
var rangeSubnets = new Array(arr.length)
|
||||
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
rangeSubnets[i] = parseipNotation(arr[i])
|
||||
}
|
||||
|
||||
return rangeSubnets
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile range subnet array into trust function.
|
||||
*
|
||||
* @param {Array} rangeSubnets
|
||||
* @private
|
||||
*/
|
||||
|
||||
function compileTrust (rangeSubnets) {
|
||||
// Return optimized function based on length
|
||||
var len = rangeSubnets.length
|
||||
return len === 0
|
||||
? trustNone
|
||||
: len === 1
|
||||
? trustSingle(rangeSubnets[0])
|
||||
: trustMulti(rangeSubnets)
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse IP notation string into range subnet.
|
||||
*
|
||||
* @param {String} note
|
||||
* @private
|
||||
*/
|
||||
|
||||
function parseipNotation (note) {
|
||||
var pos = note.lastIndexOf('/')
|
||||
var str = pos !== -1
|
||||
? note.substring(0, pos)
|
||||
: note
|
||||
|
||||
if (!isip(str)) {
|
||||
throw new TypeError('invalid IP address: ' + str)
|
||||
}
|
||||
|
||||
var ip = parseip(str)
|
||||
|
||||
if (pos === -1 && ip.kind() === 'ipv6' && ip.isIPv4MappedAddress()) {
|
||||
// Store as IPv4
|
||||
ip = ip.toIPv4Address()
|
||||
}
|
||||
|
||||
var max = ip.kind() === 'ipv6'
|
||||
? 128
|
||||
: 32
|
||||
|
||||
var range = pos !== -1
|
||||
? note.substring(pos + 1, note.length)
|
||||
: null
|
||||
|
||||
if (range === null) {
|
||||
range = max
|
||||
} else if (DIGIT_REGEXP.test(range)) {
|
||||
range = parseInt(range, 10)
|
||||
} else if (ip.kind() === 'ipv4' && isip(range)) {
|
||||
range = parseNetmask(range)
|
||||
} else {
|
||||
range = null
|
||||
}
|
||||
|
||||
if (range <= 0 || range > max) {
|
||||
throw new TypeError('invalid range on address: ' + note)
|
||||
}
|
||||
|
||||
return [ip, range]
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse netmask string into CIDR range.
|
||||
*
|
||||
* @param {String} netmask
|
||||
* @private
|
||||
*/
|
||||
|
||||
function parseNetmask (netmask) {
|
||||
var ip = parseip(netmask)
|
||||
var kind = ip.kind()
|
||||
|
||||
return kind === 'ipv4'
|
||||
? ip.prefixLengthFromSubnetMask()
|
||||
: null
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine address of proxied request.
|
||||
*
|
||||
* @param {Object} request
|
||||
* @param {Function|Array|String} trust
|
||||
* @public
|
||||
*/
|
||||
|
||||
function proxyaddr (req, trust) {
|
||||
if (!req) {
|
||||
throw new TypeError('req argument is required')
|
||||
}
|
||||
|
||||
if (!trust) {
|
||||
throw new TypeError('trust argument is required')
|
||||
}
|
||||
|
||||
var addrs = alladdrs(req, trust)
|
||||
var addr = addrs[addrs.length - 1]
|
||||
|
||||
return addr
|
||||
}
|
||||
|
||||
/**
|
||||
* Static trust function to trust nothing.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
function trustNone () {
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile trust function for multiple subnets.
|
||||
*
|
||||
* @param {Array} subnets
|
||||
* @private
|
||||
*/
|
||||
|
||||
function trustMulti (subnets) {
|
||||
return function trust (addr) {
|
||||
if (!isip(addr)) return false
|
||||
|
||||
var ip = parseip(addr)
|
||||
var ipconv
|
||||
var kind = ip.kind()
|
||||
|
||||
for (var i = 0; i < subnets.length; i++) {
|
||||
var subnet = subnets[i]
|
||||
var subnetip = subnet[0]
|
||||
var subnetkind = subnetip.kind()
|
||||
var subnetrange = subnet[1]
|
||||
var trusted = ip
|
||||
|
||||
if (kind !== subnetkind) {
|
||||
if (subnetkind === 'ipv4' && !ip.isIPv4MappedAddress()) {
|
||||
// Incompatible IP addresses
|
||||
continue
|
||||
}
|
||||
|
||||
if (!ipconv) {
|
||||
// Convert IP to match subnet IP kind
|
||||
ipconv = subnetkind === 'ipv4'
|
||||
? ip.toIPv4Address()
|
||||
: ip.toIPv4MappedAddress()
|
||||
}
|
||||
|
||||
trusted = ipconv
|
||||
}
|
||||
|
||||
if (trusted.match(subnetip, subnetrange)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile trust function for single subnet.
|
||||
*
|
||||
* @param {Object} subnet
|
||||
* @private
|
||||
*/
|
||||
|
||||
function trustSingle (subnet) {
|
||||
var subnetip = subnet[0]
|
||||
var subnetkind = subnetip.kind()
|
||||
var subnetisipv4 = subnetkind === 'ipv4'
|
||||
var subnetrange = subnet[1]
|
||||
|
||||
return function trust (addr) {
|
||||
if (!isip(addr)) return false
|
||||
|
||||
var ip = parseip(addr)
|
||||
var kind = ip.kind()
|
||||
|
||||
if (kind !== subnetkind) {
|
||||
if (subnetisipv4 && !ip.isIPv4MappedAddress()) {
|
||||
// Incompatible IP addresses
|
||||
return false
|
||||
}
|
||||
|
||||
// Convert IP to match subnet IP kind
|
||||
ip = subnetisipv4
|
||||
? ip.toIPv4Address()
|
||||
: ip.toIPv4MappedAddress()
|
||||
}
|
||||
|
||||
return ip.match(subnetip, subnetrange)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*!
|
||||
* negotiator
|
||||
* Copyright(c) 2012 Federico Romero
|
||||
* Copyright(c) 2012-2014 Isaac Z. Schlueter
|
||||
* Copyright(c) 2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var preferredCharsets = require('./lib/charset')
|
||||
var preferredEncodings = require('./lib/encoding')
|
||||
var preferredLanguages = require('./lib/language')
|
||||
var preferredMediaTypes = require('./lib/mediaType')
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
module.exports = Negotiator;
|
||||
module.exports.Negotiator = Negotiator;
|
||||
|
||||
/**
|
||||
* Create a Negotiator instance from a request.
|
||||
* @param {object} request
|
||||
* @public
|
||||
*/
|
||||
|
||||
function Negotiator(request) {
|
||||
if (!(this instanceof Negotiator)) {
|
||||
return new Negotiator(request);
|
||||
}
|
||||
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
Negotiator.prototype.charset = function charset(available) {
|
||||
var set = this.charsets(available);
|
||||
return set && set[0];
|
||||
};
|
||||
|
||||
Negotiator.prototype.charsets = function charsets(available) {
|
||||
return preferredCharsets(this.request.headers['accept-charset'], available);
|
||||
};
|
||||
|
||||
Negotiator.prototype.encoding = function encoding(available, opts) {
|
||||
var set = this.encodings(available, opts);
|
||||
return set && set[0];
|
||||
};
|
||||
|
||||
Negotiator.prototype.encodings = function encodings(available, options) {
|
||||
var opts = options || {};
|
||||
return preferredEncodings(this.request.headers['accept-encoding'], available, opts.preferred);
|
||||
};
|
||||
|
||||
Negotiator.prototype.language = function language(available) {
|
||||
var set = this.languages(available);
|
||||
return set && set[0];
|
||||
};
|
||||
|
||||
Negotiator.prototype.languages = function languages(available) {
|
||||
return preferredLanguages(this.request.headers['accept-language'], available);
|
||||
};
|
||||
|
||||
Negotiator.prototype.mediaType = function mediaType(available) {
|
||||
var set = this.mediaTypes(available);
|
||||
return set && set[0];
|
||||
};
|
||||
|
||||
Negotiator.prototype.mediaTypes = function mediaTypes(available) {
|
||||
return preferredMediaTypes(this.request.headers.accept, available);
|
||||
};
|
||||
|
||||
// Backwards compatibility
|
||||
Negotiator.prototype.preferredCharset = Negotiator.prototype.charset;
|
||||
Negotiator.prototype.preferredCharsets = Negotiator.prototype.charsets;
|
||||
Negotiator.prototype.preferredEncoding = Negotiator.prototype.encoding;
|
||||
Negotiator.prototype.preferredEncodings = Negotiator.prototype.encodings;
|
||||
Negotiator.prototype.preferredLanguage = Negotiator.prototype.language;
|
||||
Negotiator.prototype.preferredLanguages = Negotiator.prototype.languages;
|
||||
Negotiator.prototype.preferredMediaType = Negotiator.prototype.mediaType;
|
||||
Negotiator.prototype.preferredMediaTypes = Negotiator.prototype.mediaTypes;
|
||||
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"name": "semver",
|
||||
"version": "7.7.2",
|
||||
"description": "The semantic version parser used by npm.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "tap",
|
||||
"snap": "tap",
|
||||
"lint": "npm run eslint",
|
||||
"postlint": "template-oss-check",
|
||||
"lintfix": "npm run eslint -- --fix",
|
||||
"posttest": "npm run lint",
|
||||
"template-oss-apply": "template-oss-apply --force",
|
||||
"eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\""
|
||||
},
|
||||
"devDependencies": {
|
||||
"@npmcli/eslint-config": "^5.0.0",
|
||||
"@npmcli/template-oss": "4.24.3",
|
||||
"benchmark": "^2.1.4",
|
||||
"tap": "^16.0.0"
|
||||
},
|
||||
"license": "ISC",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/npm/node-semver.git"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"files": [
|
||||
"bin/",
|
||||
"lib/",
|
||||
"classes/",
|
||||
"functions/",
|
||||
"internal/",
|
||||
"ranges/",
|
||||
"index.js",
|
||||
"preload.js",
|
||||
"range.bnf"
|
||||
],
|
||||
"tap": {
|
||||
"timeout": 30,
|
||||
"coverage-map": "map.js",
|
||||
"nyc-arg": [
|
||||
"--exclude",
|
||||
"tap-snapshots/**"
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"author": "GitHub Inc.",
|
||||
"templateOSS": {
|
||||
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
|
||||
"version": "4.24.3",
|
||||
"engines": ">=10",
|
||||
"distPaths": [
|
||||
"classes/",
|
||||
"functions/",
|
||||
"internal/",
|
||||
"ranges/",
|
||||
"index.js",
|
||||
"preload.js",
|
||||
"range.bnf"
|
||||
],
|
||||
"allowPaths": [
|
||||
"/classes/",
|
||||
"/functions/",
|
||||
"/internal/",
|
||||
"/ranges/",
|
||||
"/index.js",
|
||||
"/preload.js",
|
||||
"/range.bnf",
|
||||
"/benchmarks"
|
||||
],
|
||||
"publish": "true"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
module.exports = command;
|
||||
|
||||
/**
|
||||
* command constructs the executable command to run in a shell including the
|
||||
* user script, the command arguments.
|
||||
*
|
||||
* @param {Object} settings Object as:
|
||||
* { execOptions: {
|
||||
* exec: String,
|
||||
* [script: String],
|
||||
* [scriptPosition: Number],
|
||||
* [execArgs: Array<string>]
|
||||
* }
|
||||
* }
|
||||
* @return {Object} an object with the node executable and the
|
||||
* arguments to the command
|
||||
*/
|
||||
function command(settings) {
|
||||
var options = settings.execOptions;
|
||||
var executable = options.exec;
|
||||
var args = [];
|
||||
|
||||
// after "executable" go the exec args (like --debug, etc)
|
||||
if (options.execArgs) {
|
||||
[].push.apply(args, options.execArgs);
|
||||
}
|
||||
|
||||
// then goes the user's script arguments
|
||||
if (options.args) {
|
||||
[].push.apply(args, options.args);
|
||||
}
|
||||
|
||||
// after the "executable" goes the user's script
|
||||
if (options.script) {
|
||||
args.splice((options.scriptPosition || 0) +
|
||||
options.execArgs.length, 0, options.script);
|
||||
}
|
||||
|
||||
return {
|
||||
executable: executable,
|
||||
args: args,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user