cdk-common 2.1.34 → 2.1.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +2 -2
- package/lib/main.js +1 -1
- package/node_modules/fast-uri/README.md +2 -0
- package/node_modules/fast-uri/index.js +87 -19
- package/node_modules/fast-uri/lib/utils.js +22 -1
- package/node_modules/fast-uri/package.json +1 -1
- package/node_modules/fast-uri/test/equal.test.js +9 -0
- package/node_modules/fast-uri/test/parse.test.js +5 -0
- package/node_modules/fast-uri/test/resolve.test.js +9 -0
- package/node_modules/fast-uri/test/security.test.js +133 -0
- package/package.json +1 -1
package/.jsii
CHANGED
|
@@ -12984,6 +12984,6 @@
|
|
|
12984
12984
|
"symbolId": "src/main:LambdaArmFunctionProps"
|
|
12985
12985
|
}
|
|
12986
12986
|
},
|
|
12987
|
-
"version": "2.1.
|
|
12988
|
-
"fingerprint": "
|
|
12987
|
+
"version": "2.1.35",
|
|
12988
|
+
"fingerprint": "NFDErK/8HKOBmjwZW7YyqvfsSvofOt2FOB5Or/og6Os="
|
|
12989
12989
|
}
|
package/lib/main.js
CHANGED
|
@@ -38,5 +38,5 @@ class LambdaArmFunction extends constructs_1.Construct {
|
|
|
38
38
|
}
|
|
39
39
|
exports.LambdaArmFunction = LambdaArmFunction;
|
|
40
40
|
_a = JSII_RTTI_SYMBOL_1;
|
|
41
|
-
LambdaArmFunction[_a] = { fqn: "cdk-common.LambdaArmFunction", version: "2.1.
|
|
41
|
+
LambdaArmFunction[_a] = { fqn: "cdk-common.LambdaArmFunction", version: "2.1.35" };
|
|
42
42
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9tYWluLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsbUNBQW1DO0FBQ25DLGlEQUFpRDtBQUNqRCwyQ0FBdUM7QUFLdkMsTUFBYSxpQkFBa0IsU0FBUSxzQkFBUztJQUU5QyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQTRCO1FBQ3BFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsTUFBTSxlQUFlLEdBQUcsSUFBSSxHQUFHLENBQXlCO1lBQ3RELENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEVBQUUsbUNBQW1DLENBQUM7WUFDakUsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxtQ0FBbUMsQ0FBQztZQUNqRSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLG1DQUFtQyxDQUFDO1lBQ2pFLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEVBQUUsa0NBQWtDLENBQUM7WUFDaEUsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxrQ0FBa0MsQ0FBQztZQUNoRSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLGtDQUFrQyxDQUFDO1lBQ2hFLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEVBQUUsa0NBQWtDLENBQUM7WUFDaEUsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSw4QkFBOEIsQ0FBQztZQUN4RCxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLDhCQUE4QixDQUFDO1lBQ3hELENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsNkJBQTZCLENBQUM7WUFDeEQsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSwrQkFBK0IsQ0FBQztZQUMxRCxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLCtCQUErQixDQUFDO1NBQzNELENBQUMsQ0FBQztRQUVILE1BQU0sT0FBTyxHQUFHLGVBQWUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ25ELElBQUksT0FBTyxFQUFFLENBQUM7WUFDWixHQUFHLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDL0MsQ0FBQzthQUFNLENBQUM7WUFDTixNQUFNLElBQUksS0FBSyxDQUFDLG1CQUFtQixLQUFLLENBQUMsT0FBTyx1R0FBdUcsQ0FBQyxDQUFDO1FBQzNKLENBQUM7UUFFRCxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLEVBQUU7WUFDaEUsWUFBWSxFQUFFLEtBQUssQ0FBQyxZQUFZLElBQUksTUFBTSxDQUFDLFlBQVksQ0FBQyxNQUFNO1lBQzlELEdBQUcsS0FBSztTQUNULENBQUMsQ0FBQztJQUNMLENBQUM7O0FBL0JILDhDQWdDQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGNkayBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmV4cG9ydCBpbnRlcmZhY2UgTGFtYmRhQXJtRnVuY3Rpb25Qcm9wcyBleHRlbmRzIGxhbWJkYS5GdW5jdGlvblByb3BzIHtcblxufVxuXG5leHBvcnQgY2xhc3MgTGFtYmRhQXJtRnVuY3Rpb24gZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBwdWJsaWMgcmVhZG9ubHkgbGFtYmRhRnVuY3Rpb246IGxhbWJkYS5GdW5jdGlvbjtcbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6TGFtYmRhQXJtRnVuY3Rpb25Qcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBjb25zdCBydW50aW1lV2FybmluZ3MgPSBuZXcgTWFwPGxhbWJkYS5SdW50aW1lLCBzdHJpbmc+KFtcbiAgICAgIFtsYW1iZGEuUnVudGltZS5OT0RFSlNfMjJfWCwgJ1lvdSBhcmUgdXNpbmcgTm9kZS5qcyAyMi54IGF0IEFSTSddLFxuICAgICAgW2xhbWJkYS5SdW50aW1lLk5PREVKU18yMF9YLCAnWW91IGFyZSB1c2luZyBOb2RlLmpzIDIwLnggYXQgQVJNJ10sXG4gICAgICBbbGFtYmRhLlJ1bnRpbWUuTk9ERUpTXzE4X1gsICdZb3UgYXJlIHVzaW5nIE5vZGUuanMgMTgueCBhdCBBUk0nXSxcbiAgICAgIFtsYW1iZGEuUnVudGltZS5QWVRIT05fM18xMywgJ1lvdSBhcmUgdXNpbmcgUHl0aG9uIDMuMTMgYXQgQVJNJ10sXG4gICAgICBbbGFtYmRhLlJ1bnRpbWUuUFlUSE9OXzNfMTIsICdZb3UgYXJlIHVzaW5nIFB5dGhvbiAzLjEyIGF0IEFSTSddLFxuICAgICAgW2xhbWJkYS5SdW50aW1lLlBZVEhPTl8zXzExLCAnWW91IGFyZSB1c2luZyBQeXRob24gMy4xMSBhdCBBUk0nXSxcbiAgICAgIFtsYW1iZGEuUnVudGltZS5QWVRIT05fM18xMCwgJ1lvdSBhcmUgdXNpbmcgUHl0aG9uIDMuMTAgYXQgQVJNJ10sXG4gICAgICBbbGFtYmRhLlJ1bnRpbWUuSkFWQV8yMSwgJ1lvdSBhcmUgdXNpbmcgSmF2YSAyMSBhdCBBUk0nXSxcbiAgICAgIFtsYW1iZGEuUnVudGltZS5KQVZBXzE3LCAnWW91IGFyZSB1c2luZyBKYXZhIDE3IGF0IEFSTSddLFxuICAgICAgW2xhbWJkYS5SdW50aW1lLkRPVE5FVF84LCAnWW91IGFyZSB1c2luZyAuTkVUIDggYXQgQVJNJ10sXG4gICAgICBbbGFtYmRhLlJ1bnRpbWUuUlVCWV8zXzQsICdZb3UgYXJlIHVzaW5nIFJ1YnkgMy40IGF0IEFSTSddLFxuICAgICAgW2xhbWJkYS5SdW50aW1lLlJVQllfM18zLCAnWW91IGFyZSB1c2luZyBSdWJ5IDMuMyBhdCBBUk0nXSxcbiAgICBdKTtcblxuICAgIGNvbnN0IHdhcm5pbmcgPSBydW50aW1lV2FybmluZ3MuZ2V0KHByb3BzLnJ1bnRpbWUpO1xuICAgIGlmICh3YXJuaW5nKSB7XG4gICAgICBjZGsuQW5ub3RhdGlvbnMub2YodGhpcykuYWRkV2FybmluZyh3YXJuaW5nKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIFJ1bnRpbWUgJHtwcm9wcy5ydW50aW1lfSBhdCBBUk0sIFNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vbGFtYmRhL2xhdGVzdC9kZy9mb3VuZGF0aW9uLWFyY2guaHRtbD9pY21waWQ9ZG9jc19sYW1iZGFfcnNzYCk7XG4gICAgfVxuXG4gICAgdGhpcy5sYW1iZGFGdW5jdGlvbiA9IG5ldyBsYW1iZGEuRnVuY3Rpb24odGhpcywgJ0xhbWJkYUZ1bmN0aW9uJywge1xuICAgICAgYXJjaGl0ZWN0dXJlOiBwcm9wcy5hcmNoaXRlY3R1cmUgPz8gbGFtYmRhLkFyY2hpdGVjdHVyZS5BUk1fNjQsXG4gICAgICAuLi5wcm9wcyxcbiAgICB9KTtcbiAgfVxufVxuIl19
|
|
@@ -12,6 +12,8 @@ Dependency-free RFC 3986 URI toolbox.
|
|
|
12
12
|
|
|
13
13
|
All of the above functions can accept an additional options argument that is an object that can contain one or more of the following properties:
|
|
14
14
|
|
|
15
|
+
Malformed authorities and out-of-range ports are reported through the parsed component's `error` field. `normalize()` leaves malformed string inputs unchanged, and `equal()` returns `false` when either string input is malformed.
|
|
16
|
+
|
|
15
17
|
* `scheme` (string)
|
|
16
18
|
Indicates the scheme that the URI should be treated as, overriding the URI's normal scheme parsing behavior.
|
|
17
19
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, escapePreservingEscapes, isIPv4, nonSimpleDomain } = require('./lib/utils')
|
|
3
|
+
const { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, escapePreservingEscapes, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require('./lib/utils')
|
|
4
4
|
const { SCHEMES, getSchemeHandler } = require('./lib/schemes')
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -11,7 +11,7 @@ const { SCHEMES, getSchemeHandler } = require('./lib/schemes')
|
|
|
11
11
|
*/
|
|
12
12
|
function normalize (uri, options) {
|
|
13
13
|
if (typeof uri === 'string') {
|
|
14
|
-
uri = /** @type {T} */ (
|
|
14
|
+
uri = /** @type {T} */ (normalizeString(uri, options))
|
|
15
15
|
} else if (typeof uri === 'object') {
|
|
16
16
|
uri = /** @type {T} */ (parse(serialize(uri, options), options))
|
|
17
17
|
}
|
|
@@ -106,19 +106,10 @@ function resolveComponent (base, relative, options, skipNormalization) {
|
|
|
106
106
|
* @returns {boolean}
|
|
107
107
|
*/
|
|
108
108
|
function equal (uriA, uriB, options) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
} else if (typeof uriA === 'object') {
|
|
112
|
-
uriA = serialize(uriA, options)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (typeof uriB === 'string') {
|
|
116
|
-
uriB = serialize(parse(uriB, options), options)
|
|
117
|
-
} else if (typeof uriB === 'object') {
|
|
118
|
-
uriB = serialize(uriB, options)
|
|
119
|
-
}
|
|
109
|
+
const normalizedA = normalizeComparableURI(uriA, options)
|
|
110
|
+
const normalizedB = normalizeComparableURI(uriB, options)
|
|
120
111
|
|
|
121
|
-
return
|
|
112
|
+
return normalizedA !== undefined && normalizedB !== undefined && normalizedA.toLowerCase() === normalizedB.toLowerCase()
|
|
122
113
|
}
|
|
123
114
|
|
|
124
115
|
/**
|
|
@@ -211,12 +202,29 @@ function serialize (cmpts, opts) {
|
|
|
211
202
|
|
|
212
203
|
const URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u
|
|
213
204
|
|
|
205
|
+
/**
|
|
206
|
+
* @param {import('./types/index').URIComponent} parsed
|
|
207
|
+
* @param {RegExpMatchArray} matches
|
|
208
|
+
* @returns {string|undefined}
|
|
209
|
+
*/
|
|
210
|
+
function getParseError (parsed, matches) {
|
|
211
|
+
if (matches[2] !== undefined && parsed.path && parsed.path[0] !== '/') {
|
|
212
|
+
return 'URI path must start with "/" when authority is present.'
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (typeof parsed.port === 'number' && (parsed.port < 0 || parsed.port > 65535)) {
|
|
216
|
+
return 'URI port is malformed.'
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return undefined
|
|
220
|
+
}
|
|
221
|
+
|
|
214
222
|
/**
|
|
215
223
|
* @param {string} uri
|
|
216
224
|
* @param {import('./types/index').Options} [opts]
|
|
217
|
-
* @returns
|
|
225
|
+
* @returns {{ parsed: import('./types/index').URIComponent, malformedAuthorityOrPort: boolean }}
|
|
218
226
|
*/
|
|
219
|
-
function
|
|
227
|
+
function parseWithStatus (uri, opts) {
|
|
220
228
|
const options = Object.assign({}, opts)
|
|
221
229
|
/** @type {import('./types/index').URIComponent} */
|
|
222
230
|
const parsed = {
|
|
@@ -229,6 +237,8 @@ function parse (uri, opts) {
|
|
|
229
237
|
fragment: undefined
|
|
230
238
|
}
|
|
231
239
|
|
|
240
|
+
let malformedAuthorityOrPort = false
|
|
241
|
+
|
|
232
242
|
let isIP = false
|
|
233
243
|
if (options.reference === 'suffix') {
|
|
234
244
|
if (options.scheme) {
|
|
@@ -254,6 +264,13 @@ function parse (uri, opts) {
|
|
|
254
264
|
if (isNaN(parsed.port)) {
|
|
255
265
|
parsed.port = matches[5]
|
|
256
266
|
}
|
|
267
|
+
|
|
268
|
+
const parseError = getParseError(parsed, matches)
|
|
269
|
+
if (parseError !== undefined) {
|
|
270
|
+
parsed.error = parsed.error || parseError
|
|
271
|
+
malformedAuthorityOrPort = true
|
|
272
|
+
}
|
|
273
|
+
|
|
257
274
|
if (parsed.host) {
|
|
258
275
|
const ipv4result = isIPv4(parsed.host)
|
|
259
276
|
if (ipv4result === false) {
|
|
@@ -302,14 +319,18 @@ function parse (uri, opts) {
|
|
|
302
319
|
parsed.scheme = unescape(parsed.scheme)
|
|
303
320
|
}
|
|
304
321
|
if (parsed.host !== undefined) {
|
|
305
|
-
parsed.host = unescape(parsed.host)
|
|
322
|
+
parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP)
|
|
306
323
|
}
|
|
307
324
|
}
|
|
308
325
|
if (parsed.path) {
|
|
309
326
|
parsed.path = normalizePathEncoding(parsed.path)
|
|
310
327
|
}
|
|
311
328
|
if (parsed.fragment) {
|
|
312
|
-
|
|
329
|
+
try {
|
|
330
|
+
parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment))
|
|
331
|
+
} catch {
|
|
332
|
+
parsed.error = parsed.error || 'URI malformed'
|
|
333
|
+
}
|
|
313
334
|
}
|
|
314
335
|
}
|
|
315
336
|
|
|
@@ -320,7 +341,54 @@ function parse (uri, opts) {
|
|
|
320
341
|
} else {
|
|
321
342
|
parsed.error = parsed.error || 'URI can not be parsed.'
|
|
322
343
|
}
|
|
323
|
-
return parsed
|
|
344
|
+
return { parsed, malformedAuthorityOrPort }
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* @param {string} uri
|
|
349
|
+
* @param {import('./types/index').Options} [opts]
|
|
350
|
+
* @returns
|
|
351
|
+
*/
|
|
352
|
+
function parse (uri, opts) {
|
|
353
|
+
return parseWithStatus(uri, opts).parsed
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* @param {string} uri
|
|
358
|
+
* @param {import('./types/index').Options} [opts]
|
|
359
|
+
* @returns {string}
|
|
360
|
+
*/
|
|
361
|
+
function normalizeString (uri, opts) {
|
|
362
|
+
return normalizeStringWithStatus(uri, opts).normalized
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* @param {string} uri
|
|
367
|
+
* @param {import('./types/index').Options} [opts]
|
|
368
|
+
* @returns {{ normalized: string, malformedAuthorityOrPort: boolean }}
|
|
369
|
+
*/
|
|
370
|
+
function normalizeStringWithStatus (uri, opts) {
|
|
371
|
+
const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts)
|
|
372
|
+
return {
|
|
373
|
+
normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
|
|
374
|
+
malformedAuthorityOrPort
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* @param {import ('./types/index').URIComponent|string} uri
|
|
380
|
+
* @param {import('./types/index').Options} [opts]
|
|
381
|
+
* @returns {string|undefined}
|
|
382
|
+
*/
|
|
383
|
+
function normalizeComparableURI (uri, opts) {
|
|
384
|
+
if (typeof uri === 'string') {
|
|
385
|
+
const { normalized, malformedAuthorityOrPort } = normalizeStringWithStatus(uri, opts)
|
|
386
|
+
return malformedAuthorityOrPort ? undefined : normalized
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (typeof uri === 'object') {
|
|
390
|
+
return serialize(uri, opts)
|
|
391
|
+
}
|
|
324
392
|
}
|
|
325
393
|
|
|
326
394
|
const fastUri = {
|
|
@@ -272,6 +272,26 @@ function removeDotSegments (path) {
|
|
|
272
272
|
return output.join('')
|
|
273
273
|
}
|
|
274
274
|
|
|
275
|
+
/**
|
|
276
|
+
* Re-escape RFC 3986 gen-delims that must not appear literally in the host.
|
|
277
|
+
* After the URI regex parses, these characters cannot be literal in the host
|
|
278
|
+
* field, so any that appear after decoding came from percent-encoding and
|
|
279
|
+
* must be restored to prevent authority structure changes.
|
|
280
|
+
*
|
|
281
|
+
* @param {string} host
|
|
282
|
+
* @param {boolean} isIP - true for IPv4/IPv6 hosts (skip colon re-escaping)
|
|
283
|
+
* @returns {string}
|
|
284
|
+
*/
|
|
285
|
+
const HOST_DELIMS = { '@': '%40', '/': '%2F', '?': '%3F', '#': '%23', ':': '%3A' }
|
|
286
|
+
const HOST_DELIM_RE = /[@/?#:]/g
|
|
287
|
+
const HOST_DELIM_NO_COLON_RE = /[@/?#]/g
|
|
288
|
+
|
|
289
|
+
function reescapeHostDelimiters (host, isIP) {
|
|
290
|
+
const re = isIP ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE
|
|
291
|
+
re.lastIndex = 0
|
|
292
|
+
return host.replace(re, (ch) => HOST_DELIMS[ch])
|
|
293
|
+
}
|
|
294
|
+
|
|
275
295
|
/**
|
|
276
296
|
* Normalizes percent escapes and optionally decodes only unreserved ASCII bytes.
|
|
277
297
|
* Reserved delimiters such as `%2F` and `%2E` stay escaped.
|
|
@@ -394,7 +414,7 @@ function recomposeAuthority (component) {
|
|
|
394
414
|
if (ipV6res.isIPV6 === true) {
|
|
395
415
|
host = `[${ipV6res.escapedHost}]`
|
|
396
416
|
} else {
|
|
397
|
-
host =
|
|
417
|
+
host = reescapeHostDelimiters(host, false)
|
|
398
418
|
}
|
|
399
419
|
}
|
|
400
420
|
uriTokens.push(host)
|
|
@@ -411,6 +431,7 @@ function recomposeAuthority (component) {
|
|
|
411
431
|
module.exports = {
|
|
412
432
|
nonSimpleDomain,
|
|
413
433
|
recomposeAuthority,
|
|
434
|
+
reescapeHostDelimiters,
|
|
414
435
|
normalizePercentEncoding,
|
|
415
436
|
normalizePathEncoding,
|
|
416
437
|
escapePreservingEscapes,
|
|
@@ -106,3 +106,12 @@ test('WSS Equal', (t) => {
|
|
|
106
106
|
runTest(t, suite)
|
|
107
107
|
t.end()
|
|
108
108
|
})
|
|
109
|
+
|
|
110
|
+
test('URI Equals tolerates malformed fragments', (t) => {
|
|
111
|
+
t.equal(
|
|
112
|
+
fastURI.equal('http://example.com/#%E0%A4A', 'http://example.com/#%E0%A4A'),
|
|
113
|
+
true,
|
|
114
|
+
'malformed fragment does not throw during equality checks'
|
|
115
|
+
)
|
|
116
|
+
t.end()
|
|
117
|
+
})
|
|
@@ -150,6 +150,11 @@ test('URI parse', (t) => {
|
|
|
150
150
|
t.equal(components.query, undefined, 'query')
|
|
151
151
|
t.equal(components.fragment, '%0D', 'fragment')
|
|
152
152
|
|
|
153
|
+
// malformed percent-encoded fragment must not throw
|
|
154
|
+
components = fastURI.parse('http://example.com/#%E0%A4A')
|
|
155
|
+
t.equal(components.error, 'URI malformed', 'malformed fragment errors')
|
|
156
|
+
t.equal(components.fragment, '%E0%A4A', 'malformed fragment is preserved')
|
|
157
|
+
|
|
153
158
|
// all
|
|
154
159
|
components = fastURI.parse('uri://user:pass@example.com:123/one/two.three?q1=a1&q2=a2#body')
|
|
155
160
|
t.equal(components.error, undefined, 'all errors')
|
|
@@ -76,3 +76,12 @@ test('URN Resolving', (t) => {
|
|
|
76
76
|
t.equal(fastURI.resolve('urn:some:other:prop', 'urn:some:ip:prop'), 'urn:some:ip:prop', 'urn:some:ip:prop')
|
|
77
77
|
t.end()
|
|
78
78
|
})
|
|
79
|
+
|
|
80
|
+
test('URI Resolving tolerates malformed fragments', (t) => {
|
|
81
|
+
t.equal(
|
|
82
|
+
fastURI.resolve('http://base.com/', 'http://example.com/#%E0%A4A'),
|
|
83
|
+
'http://example.com/#%E0%A4A',
|
|
84
|
+
'malformed fragment does not throw during resolve'
|
|
85
|
+
)
|
|
86
|
+
t.end()
|
|
87
|
+
})
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const test = require('tape')
|
|
4
|
+
const fastURI = require('..')
|
|
5
|
+
|
|
6
|
+
test('parse marks malformed authority and port inputs as errors', (t) => {
|
|
7
|
+
const malformedCases = [
|
|
8
|
+
{
|
|
9
|
+
input: 'http://[::1]foo',
|
|
10
|
+
expectedError: 'URI path must start with "/" when authority is present.'
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
input: 'http://[::1]:80abc/path',
|
|
14
|
+
expectedError: 'URI path must start with "/" when authority is present.'
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
input: 'http://example.com:80abc/path',
|
|
18
|
+
expectedError: 'URI path must start with "/" when authority is present.'
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
input: 'http://[::1]:65536',
|
|
22
|
+
expectedError: 'URI port is malformed.'
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
t.plan(malformedCases.length)
|
|
27
|
+
|
|
28
|
+
malformedCases.forEach(({ input, expectedError }) => {
|
|
29
|
+
t.equal(fastURI.parse(input).error, expectedError, input)
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test('normalize does not canonicalize malformed URLs into different valid URLs', (t) => {
|
|
34
|
+
const malformedCases = [
|
|
35
|
+
'http://[::1]foo',
|
|
36
|
+
'http://[::1]:80abc/path',
|
|
37
|
+
'http://example.com:80abc/path',
|
|
38
|
+
'http://[::1]:65536'
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
t.plan(malformedCases.length)
|
|
42
|
+
|
|
43
|
+
malformedCases.forEach((input) => {
|
|
44
|
+
t.equal(fastURI.normalize(input), input, input)
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test('equal returns false when either side is malformed', (t) => {
|
|
49
|
+
const malformedPairs = [
|
|
50
|
+
['http://[::1]foo', 'http://[::1]/foo'],
|
|
51
|
+
['http://[::1]:80abc/path', 'http://[::1]/abc/path'],
|
|
52
|
+
['http://example.com:80abc/path', 'http://example.com/abc/path'],
|
|
53
|
+
['http://[::1]:65536', 'http://[::1]:65536/']
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
t.plan(malformedPairs.length)
|
|
57
|
+
|
|
58
|
+
malformedPairs.forEach(([left, right]) => {
|
|
59
|
+
t.equal(fastURI.equal(left, right), false, `${left} != ${right}`)
|
|
60
|
+
})
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('normalize preserves encoded authority delimiters in host', (t) => {
|
|
64
|
+
const cases = [
|
|
65
|
+
['http://trusted.com%40evil.com/', 'http://trusted.com%40evil.com/'],
|
|
66
|
+
['http://example.com%3A8080/', 'http://example.com%3A8080/'],
|
|
67
|
+
['http://example.com%2Fevil.com/path', 'http://example.com%2Fevil.com/path'],
|
|
68
|
+
['http://example.com%23fragment/path', 'http://example.com%23fragment/path'],
|
|
69
|
+
['http://example.com%3Fq=evil/path', 'http://example.com%3Fq=evil/path'],
|
|
70
|
+
['http://user%3Apass%40evil.com/', 'http://user%3Apass%40evil.com/'],
|
|
71
|
+
['http://user@trusted.com%40evil.com/', 'http://user@trusted.com%40evil.com/'],
|
|
72
|
+
['https://trusted.com%40evil.com/', 'https://trusted.com%40evil.com/'],
|
|
73
|
+
['ws://trusted.com%40evil.com/chat', 'ws://trusted.com%40evil.com/chat'],
|
|
74
|
+
['wss://trusted.com%40evil.com/chat', 'wss://trusted.com%40evil.com/chat']
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
t.plan(cases.length)
|
|
78
|
+
|
|
79
|
+
cases.forEach(([input, expected]) => {
|
|
80
|
+
t.equal(fastURI.normalize(input), expected, input)
|
|
81
|
+
})
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
test('parse preserves encoded authority delimiters in host', (t) => {
|
|
85
|
+
const cases = [
|
|
86
|
+
['http://trusted.com%40evil.com/', 'trusted.com%40evil.com'],
|
|
87
|
+
['http://example.com%3A8080/', 'example.com%3A8080'],
|
|
88
|
+
['http://user%3Apass%40evil.com/', 'user%3Apass%40evil.com']
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
t.plan(cases.length)
|
|
92
|
+
|
|
93
|
+
cases.forEach(([input, expectedHost]) => {
|
|
94
|
+
t.equal(fastURI.parse(input).host, expectedHost, input)
|
|
95
|
+
})
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
test('equal returns false when encoded delimiters differ from live delimiters', (t) => {
|
|
99
|
+
const pairs = [
|
|
100
|
+
['http://trusted.com%40evil.com/', 'http://trusted.com@evil.com/'],
|
|
101
|
+
['http://example.com%3A8080/', 'http://example.com:8080/']
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
t.plan(pairs.length)
|
|
105
|
+
|
|
106
|
+
pairs.forEach(([left, right]) => {
|
|
107
|
+
t.equal(fastURI.equal(left, right, {}), false, `${left} != ${right}`)
|
|
108
|
+
})
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
test('resolve preserves encoded authority delimiters', (t) => {
|
|
112
|
+
const result = fastURI.resolve('http://base.com/', '//trusted.com%40evil.com/path')
|
|
113
|
+
const parsed = fastURI.parse(result)
|
|
114
|
+
|
|
115
|
+
t.plan(1)
|
|
116
|
+
t.notEqual(parsed.host, 'evil.com', '//trusted.com%40evil.com/path')
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
test('serialize escapes authority delimiters in host field', (t) => {
|
|
120
|
+
const result = fastURI.serialize({ scheme: 'http', host: 'trusted.com@evil.com', path: '/' })
|
|
121
|
+
const parsed = fastURI.parse(result)
|
|
122
|
+
|
|
123
|
+
t.plan(1)
|
|
124
|
+
t.notEqual(parsed.host, 'evil.com', 'host: trusted.com@evil.com')
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
test('normalize does not double-decode %2540 into a live @', (t) => {
|
|
128
|
+
const result = fastURI.normalize('http://trusted.com%2540evil.com/')
|
|
129
|
+
const parsed = fastURI.parse(result)
|
|
130
|
+
|
|
131
|
+
t.plan(1)
|
|
132
|
+
t.notEqual(parsed.host, 'trusted.com@evil.com', 'http://trusted.com%2540evil.com/')
|
|
133
|
+
})
|