@polka/url
Advanced tools
Comparing version 1.0.0-next.12 to 1.0.0-next.15
78
build.js
@@ -1,50 +0,52 @@ | ||
function parse(str) { | ||
let i=0, j=0, k, v; | ||
let out={}, arr=str.split('&'); | ||
for (; i < arr.length; i++) { | ||
j = arr[i].indexOf('='); | ||
v = !!~j && arr[i].substring(j+1) || ''; | ||
k = !!~j ? arr[i].substring(0, j) : arr[i]; | ||
out[k] = out[k] !== void 0 ? [].concat(out[k], v) : v; | ||
} | ||
return out; | ||
} | ||
const qs = require('querystring'); | ||
module.exports = function (req, toDecode) { | ||
let url = req.url; | ||
if (url == null) return; | ||
/** | ||
* @typedef ParsedURL | ||
* @type {import('.').ParsedURL} | ||
*/ | ||
let obj = req._parsedUrl; | ||
if (obj && obj._raw === url) return obj; | ||
/** | ||
* @typedef Request | ||
* @property {string} url | ||
* @property {boolean} _decoded | ||
* @property {ParsedURL} _parsedUrl | ||
*/ | ||
obj = { | ||
path: url, | ||
pathname: url, | ||
search: null, | ||
query: null, | ||
href: url, | ||
_raw: url | ||
}; | ||
/** | ||
* @param {Request} req | ||
* @param {boolean} [toDecode] | ||
* @returns {ParsedURL|void} | ||
*/ | ||
function parse(req, toDecode) { | ||
let raw = req.url; | ||
if (raw == null) return; | ||
if (url.length > 1) { | ||
if (toDecode && !req._decoded && !!~url.indexOf('%', 1)) { | ||
let nxt = url; | ||
try { nxt = decodeURIComponent(url) } catch (e) {/* bad */} | ||
url = req.url = obj.href = obj.path = obj.pathname = obj._raw = nxt; | ||
req._decoded = true; | ||
} | ||
let prev = req._parsedUrl; | ||
if (prev && prev.raw === raw) return prev; | ||
let idx = url.indexOf('?', 1); | ||
let pathname=raw, search='', query; | ||
if (raw.length > 1) { | ||
let idx = raw.indexOf('?', 1); | ||
if (idx !== -1) { | ||
obj.search = url.substring(idx); | ||
obj.query = obj.search.substring(1); | ||
obj.pathname = url.substring(0, idx); | ||
if (toDecode && obj.query.length > 0) { | ||
obj.query = parse(obj.query); | ||
search = raw.substring(idx); | ||
pathname = raw.substring(0, idx); | ||
if (search.length > 1) { | ||
query = qs.parse(search.substring(1)); | ||
} | ||
} | ||
if (!!toDecode && !req._decoded) { | ||
req._decoded = true; | ||
if (pathname.indexOf('%') !== -1) { | ||
try { pathname = decodeURIComponent(pathname) } | ||
catch (e) { /* URI malformed */ } | ||
} | ||
} | ||
} | ||
return (req._parsedUrl = obj); | ||
return req._parsedUrl = { pathname, search, query, raw }; | ||
} | ||
exports.parse = parse; |
import type { IncomingMessage } from 'http'; | ||
import type { ParsedUrlQuery } from 'querystring'; | ||
export interface ParsedURL { | ||
path: string; | ||
pathname: string; | ||
search: string | null; | ||
query: Record<string, string | string[]> | string | null; | ||
href: string; | ||
_raw: string; | ||
search: string; | ||
query: Record<string, string | string[]> | void; | ||
raw: string; | ||
} | ||
export default function (req: IncomingMessage, toDecode?: boolean): ParsedURL; | ||
export function parse(req: IncomingMessage, toDecode?: boolean): ParsedURL; |
{ | ||
"version": "1.0.0-next.12", | ||
"version": "1.0.0-next.15", | ||
"name": "@polka/url", | ||
@@ -10,2 +10,9 @@ "repository": "lukeed/polka", | ||
"license": "MIT", | ||
"exports": { | ||
".": { | ||
"import": "./build.mjs", | ||
"require": "./build.js" | ||
}, | ||
"./package.json": "./package.json" | ||
}, | ||
"files": [ | ||
@@ -23,3 +30,3 @@ "*.d.ts", | ||
}, | ||
"gitHead": "dc4a3c4b677dda9d38386299e83e84a3220e49c9" | ||
"gitHead": "e0e131dd28b03e26652a96b9a1428c017209e187" | ||
} |
@@ -5,7 +5,7 @@ # @polka/url [![npm](https://badgen.now.sh/npm/v/@polka/url)](https://npmjs.org/package/@polka/url) | ||
Parses the `url` from a [`IncomingMessage`](https://nodejs.org/api/http.html#http_class_http_incomingmessage) request. The returned object will always only contain the following keys: `search`, `query`, `pathname`, `path`, `href`, and `_raw`. | ||
Parses the `url` from a [`IncomingMessage`](https://nodejs.org/api/http.html#http_class_http_incomingmessage) request. The returned object will always only contain the following keys: `search`, `query`, `pathname`, and `raw`. | ||
> **Note:** This library does not process `protocol`, `hostname`, `port`, etc.<br>This is because the incoming `req.url` value only begins with the path information. | ||
Parsed requests will be mutated with a `_parsedUrl` key, containing the returned output. This is used for future memoization, so as to avoid parsing the same `url` value multiple times. | ||
Parsed requests will be mutated with a `_parsedUrl` key, containing the returned output. This is used for future memoization, avoiding the need to fully parse the same `url` value multiple times. | ||
@@ -23,23 +23,31 @@ ## Install | ||
let req = { url: '/foo/bar?fizz=buzz' }; | ||
let foo = parse(req); | ||
//=> { search: '?fizz=buzz', | ||
//=> query: 'fizz=buzz', | ||
let req = { | ||
url: '/foo/bar?fizz=buzz' | ||
}; | ||
let output = parse(req); | ||
//=> { | ||
//=> pathname: '/foo/bar', | ||
//=> path: '/foo/bar?fizz=buzz', | ||
//=> href: '/foo/bar?fizz=buzz', | ||
//=> _raw: '/foo/bar?fizz=buzz' } | ||
//=> raw: '/foo/bar?fizz=buzz', | ||
//=> search: '?fizz=buzz', | ||
//=> query: { | ||
//=> fizz: 'buzz' | ||
//=> }, | ||
//=> } | ||
// Attaches result for future memoization | ||
assert.deepEqual(foo, req._parsedUrl); //=> true | ||
assert.deepEqual(output, req._parsedUrl); //=> true | ||
// Example with `toDecode` param | ||
req = { url: '/f%C3%B8%C3%B8%C3%9F%E2%88%82r?phone=%2b8675309' }; | ||
req = { | ||
url: '/f%C3%B8%C3%B8%C3%9F%E2%88%82r?phone=%2b8675309' | ||
}; | ||
parse(req, true); | ||
//=> { search: '?phone=+8675309', | ||
//=> query: { phone: '+8675309' }, | ||
//=> { | ||
//=> pathname: '/føøß∂r', | ||
//=> path: '/føøß∂r?phone=+8675309', | ||
//=> href: '/føøß∂r?phone=+8675309', | ||
//=> _raw: '/føøß∂r?phone=+8675309' } | ||
//=> raw: '/f%C3%B8%C3%B8%C3%9F%E2%88%82r?phone=%2b8675309', | ||
//=> search: '?phone=%2b8675309', | ||
//=> query: { | ||
//=> phone: '+8675309' | ||
//=> } | ||
//=> } | ||
@@ -52,3 +60,3 @@ // Attaches awareness key | ||
### url(req, toDecode) | ||
### url(req, toDecode?) | ||
Returns: `Object` or `undefined` | ||
@@ -59,3 +67,3 @@ | ||
#### req | ||
Type: `IncomingMessage` or `Object` | ||
Type: `IncomingMessage` or `{ url: string }` | ||
@@ -70,7 +78,9 @@ The incoming HTTP request (`req`) or a plain `Object` with a `url` key. | ||
If enabled, the `url` will be fully decoded (via [`decodeURIComponent`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent)) and the output keys will be slightly different: | ||
If enabled, the `pathname` will be fully decoded, via [`decodeURIComponent`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent). | ||
* `path`, `pathname`, `href`, `_raw` — will be the decoded strings | ||
* `search` — if there is a value, will be decoded string, else remain `null` | ||
* `query` — if there is a value, will be a decoded **object**, else remain `null` | ||
> **Important:** Please note the following behaviors: | ||
> * `raw` is _never_ decoded; this key reflects your original value | ||
> * `pathname` is decoded _only_ when `toDecode` is enabled | ||
> * `search` is _never_ decoded; this key reflects your original querystring value | ||
> * `query` is _always_ decoded; even when `toDecode` is disabled | ||
@@ -77,0 +87,0 @@ Additionally, the `req` is mutated with `req._decoded = true` so as to prevent repetitive decoding. |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
100
7198
91