repocairn 0.1.6 → 0.1.7
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/node_modules/fast-uri/index.js +201 -48
- package/node_modules/fast-uri/lib/schemes.js +9 -4
- package/node_modules/fast-uri/lib/utils.js +388 -91
- package/node_modules/fast-uri/package.json +1 -1
- package/node_modules/fast-uri/test/component-safe-serialization.test.js +105 -0
- package/node_modules/fast-uri/test/equal.test.js +31 -3
- package/node_modules/fast-uri/test/fixtures/uri-js-parse.json +2 -0
- package/node_modules/fast-uri/test/ipv6-canonical.test.js +34 -0
- package/node_modules/fast-uri/test/ipv6-validation.test.js +90 -0
- package/node_modules/fast-uri/test/malformed-percent.test.js +77 -0
- package/node_modules/fast-uri/test/malformed-urn.test.js +61 -0
- package/node_modules/fast-uri/test/parse.test.js +7 -3
- package/node_modules/fast-uri/test/query-fragment-normalization.test.js +33 -0
- package/node_modules/fast-uri/test/reserved-path-normalization.test.js +109 -0
- package/node_modules/fast-uri/test/scheme-validation.test.js +124 -0
- package/node_modules/fast-uri/test/security-normalization.test.js +101 -0
- package/node_modules/fast-uri/test/security.test.js +75 -3
- package/node_modules/fast-uri/test/urn-full-input.test.js +29 -0
- package/node_modules/fast-uri/test/websocket-query-preservation.test.js +24 -0
- package/node_modules/jose/dist/types/jwks/remote.d.ts +4 -4
- package/node_modules/jose/dist/types/jws/general/verify.d.ts +3 -3
- package/node_modules/jose/dist/types/jwt/encrypt.d.ts +8 -14
- package/node_modules/jose/dist/types/jwt/sign.d.ts +8 -14
- package/node_modules/jose/dist/types/jwt/unsecured.d.ts +9 -15
- package/node_modules/jose/dist/webapi/jwe/compact/encrypt.js +30 -8
- package/node_modules/jose/dist/webapi/jwe/flattened/decrypt.js +8 -4
- package/node_modules/jose/dist/webapi/jwe/flattened/encrypt.js +6 -13
- package/node_modules/jose/dist/webapi/jwe/general/decrypt.js +19 -19
- package/node_modules/jose/dist/webapi/jwe/general/encrypt.js +27 -20
- package/node_modules/jose/dist/webapi/jwk/embedded.js +15 -1
- package/node_modules/jose/dist/webapi/jwk/thumbprint.js +11 -5
- package/node_modules/jose/dist/webapi/jwks/local.js +45 -53
- package/node_modules/jose/dist/webapi/jwks/remote.js +82 -103
- package/node_modules/jose/dist/webapi/jws/compact/sign.js +10 -9
- package/node_modules/jose/dist/webapi/jws/flattened/sign.js +2 -1
- package/node_modules/jose/dist/webapi/jws/flattened/verify.js +8 -7
- package/node_modules/jose/dist/webapi/jws/general/sign.js +5 -3
- package/node_modules/jose/dist/webapi/jws/general/verify.js +51 -21
- package/node_modules/jose/dist/webapi/jwt/decrypt.js +7 -9
- package/node_modules/jose/dist/webapi/jwt/encrypt.js +21 -50
- package/node_modules/jose/dist/webapi/jwt/sign.js +8 -41
- package/node_modules/jose/dist/webapi/jwt/unsecured.js +21 -42
- package/node_modules/jose/dist/webapi/key/generate_key_pair.js +6 -2
- package/node_modules/jose/dist/webapi/key/generate_secret.js +7 -6
- package/node_modules/jose/dist/webapi/key/import.js +16 -12
- package/node_modules/jose/dist/webapi/lib/asn1.js +7 -2
- package/node_modules/jose/dist/webapi/lib/content_encryption.js +7 -15
- package/node_modules/jose/dist/webapi/lib/deflate.js +8 -0
- package/node_modules/jose/dist/webapi/lib/helpers.js +1 -1
- package/node_modules/jose/dist/webapi/lib/jwe_decrypt.js +85 -28
- package/node_modules/jose/dist/webapi/lib/jwe_encrypt.js +40 -12
- package/node_modules/jose/dist/webapi/lib/jwk_metadata.js +20 -0
- package/node_modules/jose/dist/webapi/lib/jws_sign.js +47 -36
- package/node_modules/jose/dist/webapi/lib/jws_verify.js +77 -45
- package/node_modules/jose/dist/webapi/lib/jwt_claims_set.js +82 -47
- package/node_modules/jose/dist/webapi/lib/key.js +24 -9
- package/node_modules/jose/dist/webapi/lib/key_management.js +10 -4
- package/node_modules/jose/dist/webapi/lib/key_options.js +6 -0
- package/node_modules/jose/dist/webapi/lib/options.js +26 -0
- package/node_modules/jose/dist/webapi/lib/type_checks.js +11 -13
- package/node_modules/jose/package.json +1 -1
- package/package.json +1 -1
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding,
|
|
3
|
+
const { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, serializePathEncoding, normalizeQueryFragmentEncoding, encodeQuery, encodeFragment, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require('./lib/utils')
|
|
4
4
|
const { SCHEMES, getSchemeHandler } = require('./lib/schemes')
|
|
5
5
|
|
|
6
|
+
const VALID_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*$/u
|
|
7
|
+
const MALFORMED_SCHEME_ERROR = 'URI scheme is malformed.'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {string} scheme
|
|
11
|
+
* @returns {string}
|
|
12
|
+
*/
|
|
13
|
+
function decodeValidScheme (scheme) {
|
|
14
|
+
const decodedScheme = unescape(String(scheme))
|
|
15
|
+
if (!VALID_SCHEME.test(decodedScheme)) {
|
|
16
|
+
throw new TypeError(MALFORMED_SCHEME_ERROR)
|
|
17
|
+
}
|
|
18
|
+
return decodedScheme
|
|
19
|
+
}
|
|
20
|
+
|
|
6
21
|
/**
|
|
7
22
|
* @template {import('./types/index').URIComponent|string} T
|
|
8
23
|
* @param {T} uri
|
|
@@ -26,12 +41,50 @@ function normalize (uri, options) {
|
|
|
26
41
|
*/
|
|
27
42
|
function resolve (baseURI, relativeURI, options) {
|
|
28
43
|
const schemelessOptions = options ? Object.assign({ scheme: 'null' }, options) : { scheme: 'null' }
|
|
29
|
-
const {
|
|
30
|
-
|
|
31
|
-
|
|
44
|
+
const {
|
|
45
|
+
parsed: baseParsed,
|
|
46
|
+
malformedAuthorityOrPort: baseMalformed,
|
|
47
|
+
malformedPercentEncoding: baseMalformedPercentEncoding,
|
|
48
|
+
malformedSchemeSpecific: baseMalformedSchemeSpecific,
|
|
49
|
+
malformedHost: baseMalformedHost,
|
|
50
|
+
malformedScheme: baseMalformedScheme
|
|
51
|
+
} = parseWithStatus(baseURI, schemelessOptions)
|
|
52
|
+
const {
|
|
53
|
+
parsed: relativeParsed,
|
|
54
|
+
malformedAuthorityOrPort: relativeMalformed,
|
|
55
|
+
malformedPercentEncoding: relativeMalformedPercentEncoding,
|
|
56
|
+
malformedSchemeSpecific: relativeMalformedSchemeSpecific,
|
|
57
|
+
malformedHost: relativeMalformedHost,
|
|
58
|
+
malformedScheme: relativeMalformedScheme
|
|
59
|
+
} = parseWithStatus(relativeURI, schemelessOptions)
|
|
60
|
+
if (
|
|
61
|
+
baseMalformed ||
|
|
62
|
+
relativeMalformed ||
|
|
63
|
+
baseMalformedPercentEncoding ||
|
|
64
|
+
relativeMalformedPercentEncoding ||
|
|
65
|
+
baseMalformedSchemeSpecific ||
|
|
66
|
+
relativeMalformedSchemeSpecific ||
|
|
67
|
+
baseMalformedHost ||
|
|
68
|
+
relativeMalformedHost ||
|
|
69
|
+
baseMalformedScheme ||
|
|
70
|
+
relativeMalformedScheme
|
|
71
|
+
) {
|
|
32
72
|
throw new Error(baseParsed.error || relativeParsed.error || 'URI is malformed.')
|
|
33
73
|
}
|
|
34
74
|
const resolved = resolveComponent(baseParsed, relativeParsed, schemelessOptions, true)
|
|
75
|
+
const resolvedSchemeHandler = getSchemeHandler((options && options.scheme) || resolved.scheme)
|
|
76
|
+
const resolvedHost = resolved.host
|
|
77
|
+
const resolvedHostIsIP = resolvedHost !== undefined && resolvedHost !== '' &&
|
|
78
|
+
(isIPv4(resolvedHost) || normalizeIPv6(resolvedHost).isIPV6)
|
|
79
|
+
canonicalizeHost(resolved, options || {}, resolvedSchemeHandler, resolvedHostIsIP)
|
|
80
|
+
// Percent escapes in an ASCII reg-name are encoded data. The WHATWG hostname
|
|
81
|
+
// parser can reject them even though fast-uri preserves them safely as RFC
|
|
82
|
+
// 3986 data. A raw non-ASCII host must still fail closed if conversion fails.
|
|
83
|
+
const encodedASCIIHost = resolvedHost && resolvedHost.indexOf('%') !== -1 &&
|
|
84
|
+
!/\P{ASCII}/u.test(resolvedHost)
|
|
85
|
+
if (resolved.error && !encodedASCIIHost) {
|
|
86
|
+
throw new Error(resolved.error)
|
|
87
|
+
}
|
|
35
88
|
schemelessOptions.skipEscape = true
|
|
36
89
|
return serialize(resolved, schemelessOptions)
|
|
37
90
|
}
|
|
@@ -114,7 +167,7 @@ function equal (uriA, uriB, options) {
|
|
|
114
167
|
const normalizedA = normalizeComparableURI(uriA, options)
|
|
115
168
|
const normalizedB = normalizeComparableURI(uriB, options)
|
|
116
169
|
|
|
117
|
-
return normalizedA !== undefined && normalizedB !== undefined && normalizedA
|
|
170
|
+
return normalizedA !== undefined && normalizedB !== undefined && normalizedA === normalizedB
|
|
118
171
|
}
|
|
119
172
|
|
|
120
173
|
/**
|
|
@@ -142,25 +195,30 @@ function serialize (cmpts, opts) {
|
|
|
142
195
|
const options = Object.assign({}, opts)
|
|
143
196
|
const uriTokens = []
|
|
144
197
|
|
|
198
|
+
if (component.scheme) {
|
|
199
|
+
component.scheme = decodeValidScheme(component.scheme)
|
|
200
|
+
}
|
|
201
|
+
|
|
145
202
|
// find scheme handler
|
|
146
203
|
const schemeHandler = getSchemeHandler(options.scheme || component.scheme)
|
|
147
204
|
|
|
148
205
|
// perform scheme specific serialization
|
|
149
206
|
if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component, options)
|
|
150
207
|
|
|
208
|
+
const hasAuthority = component.userinfo !== undefined || component.host !== undefined || component.port !== undefined
|
|
209
|
+
const pathNoScheme = !options.skipEscape && component.scheme === undefined && !hasAuthority
|
|
210
|
+
|
|
151
211
|
if (component.path !== undefined) {
|
|
152
212
|
if (!options.skipEscape) {
|
|
153
|
-
component.path =
|
|
154
|
-
|
|
155
|
-
if (component.scheme !== undefined) {
|
|
156
|
-
component.path = component.path.split('%3A').join(':')
|
|
157
|
-
}
|
|
213
|
+
component.path = serializePathEncoding(component.path, pathNoScheme)
|
|
158
214
|
} else {
|
|
159
215
|
component.path = normalizePercentEncoding(component.path)
|
|
160
216
|
}
|
|
161
217
|
}
|
|
162
218
|
|
|
163
219
|
if (options.reference !== 'suffix' && component.scheme) {
|
|
220
|
+
// Scheme handlers may replace the scheme during serialization.
|
|
221
|
+
component.scheme = decodeValidScheme(component.scheme)
|
|
164
222
|
uriTokens.push(component.scheme, ':')
|
|
165
223
|
}
|
|
166
224
|
|
|
@@ -183,6 +241,13 @@ function serialize (cmpts, opts) {
|
|
|
183
241
|
s = removeDotSegments(s)
|
|
184
242
|
}
|
|
185
243
|
|
|
244
|
+
// Dot-segment removal can expose a colon that was not originally in the
|
|
245
|
+
// first segment (for example, "./a:b"). Reapply path-noscheme encoding so
|
|
246
|
+
// the serialized relative reference cannot be reparsed as a URI scheme.
|
|
247
|
+
if (pathNoScheme) {
|
|
248
|
+
s = serializePathEncoding(s, true)
|
|
249
|
+
}
|
|
250
|
+
|
|
186
251
|
if (
|
|
187
252
|
authority === undefined &&
|
|
188
253
|
s[0] === '/' &&
|
|
@@ -196,11 +261,11 @@ function serialize (cmpts, opts) {
|
|
|
196
261
|
}
|
|
197
262
|
|
|
198
263
|
if (component.query !== undefined) {
|
|
199
|
-
uriTokens.push('?', component.query)
|
|
264
|
+
uriTokens.push('?', encodeQuery(component.query))
|
|
200
265
|
}
|
|
201
266
|
|
|
202
267
|
if (component.fragment !== undefined) {
|
|
203
|
-
uriTokens.push('#', component.fragment)
|
|
268
|
+
uriTokens.push('#', encodeFragment(component.fragment))
|
|
204
269
|
}
|
|
205
270
|
return uriTokens.join('')
|
|
206
271
|
}
|
|
@@ -237,10 +302,74 @@ function getParseError (parsed, matches) {
|
|
|
237
302
|
return undefined
|
|
238
303
|
}
|
|
239
304
|
|
|
305
|
+
/**
|
|
306
|
+
* Checks percent syntax without decoding the represented octets. RFC 3986
|
|
307
|
+
* percent-encoding is byte-oriented, so sequences such as `%FF` are valid even
|
|
308
|
+
* though they are not independently valid UTF-8.
|
|
309
|
+
*
|
|
310
|
+
* @param {string|undefined} component
|
|
311
|
+
* @returns {boolean}
|
|
312
|
+
*/
|
|
313
|
+
function hasMalformedPercentEncoding (component) {
|
|
314
|
+
if (component === undefined) return false
|
|
315
|
+
|
|
316
|
+
let percent = component.indexOf('%')
|
|
317
|
+
while (percent !== -1) {
|
|
318
|
+
if (percent + 2 >= component.length || !/^[\da-f]{2}$/iu.test(component.slice(percent + 1, percent + 3))) {
|
|
319
|
+
return true
|
|
320
|
+
}
|
|
321
|
+
percent = component.indexOf('%', percent + 3)
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return false
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* @param {RegExpMatchArray} matches
|
|
329
|
+
* @returns {boolean}
|
|
330
|
+
*/
|
|
331
|
+
function hasMalformedComponentPercentEncoding (matches) {
|
|
332
|
+
// Bracketed IP literals use a raw "%" as the zone separator for historical
|
|
333
|
+
// compatibility. Their parsing is intentionally left to normalizeIPv6.
|
|
334
|
+
const host = matches[4]
|
|
335
|
+
return hasMalformedPercentEncoding(matches[3]) ||
|
|
336
|
+
(host !== undefined && !(host[0] === '[' && host[host.length - 1] === ']') && hasMalformedPercentEncoding(host)) ||
|
|
337
|
+
hasMalformedPercentEncoding(matches[6]) ||
|
|
338
|
+
hasMalformedPercentEncoding(matches[7]) ||
|
|
339
|
+
hasMalformedPercentEncoding(matches[8])
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* @param {import('./types/index').URIComponent} parsed
|
|
344
|
+
* @param {import('./types/index').Options} options
|
|
345
|
+
* @param {{ domainHost?: boolean, unicodeSupport?: boolean }|undefined} schemeHandler
|
|
346
|
+
* @param {boolean} isIP
|
|
347
|
+
* @returns {boolean} whether host conversion failed
|
|
348
|
+
*/
|
|
349
|
+
function canonicalizeHost (parsed, options, schemeHandler, isIP) {
|
|
350
|
+
if (
|
|
351
|
+
!options.unicodeSupport &&
|
|
352
|
+
(!schemeHandler || !schemeHandler.unicodeSupport) &&
|
|
353
|
+
parsed.host &&
|
|
354
|
+
parsed.host[0] !== '[' &&
|
|
355
|
+
(options.domainHost || (schemeHandler && schemeHandler.domainHost)) &&
|
|
356
|
+
isIP === false &&
|
|
357
|
+
nonSimpleDomain(parsed.host)
|
|
358
|
+
) {
|
|
359
|
+
try {
|
|
360
|
+
parsed.host = new URL('http://' + parsed.host).hostname
|
|
361
|
+
} catch (e) {
|
|
362
|
+
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e
|
|
363
|
+
return true
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return false
|
|
367
|
+
}
|
|
368
|
+
|
|
240
369
|
/**
|
|
241
370
|
* @param {string} uri
|
|
242
371
|
* @param {import('./types/index').Options} [opts]
|
|
243
|
-
* @returns {{ parsed: import('./types/index').URIComponent, malformedAuthorityOrPort: boolean }}
|
|
372
|
+
* @returns {{ parsed: import('./types/index').URIComponent, malformedAuthorityOrPort: boolean, malformedPercentEncoding: boolean, malformedSchemeSpecific: boolean, malformedHost: boolean, malformedScheme: boolean }}
|
|
244
373
|
*/
|
|
245
374
|
function parseWithStatus (uri, opts) {
|
|
246
375
|
const options = Object.assign({}, opts)
|
|
@@ -256,6 +385,11 @@ function parseWithStatus (uri, opts) {
|
|
|
256
385
|
}
|
|
257
386
|
|
|
258
387
|
let malformedAuthorityOrPort = false
|
|
388
|
+
let malformedPercentEncoding = false
|
|
389
|
+
let malformedSchemeSpecific = false
|
|
390
|
+
let malformedHost = false
|
|
391
|
+
let malformedIPLiteral = false
|
|
392
|
+
let malformedScheme = false
|
|
259
393
|
|
|
260
394
|
let isIP = false
|
|
261
395
|
if (options.reference === 'suffix') {
|
|
@@ -313,6 +447,21 @@ function parseWithStatus (uri, opts) {
|
|
|
313
447
|
parsed.query = matches[7]
|
|
314
448
|
parsed.fragment = matches[8]
|
|
315
449
|
|
|
450
|
+
if (parsed.scheme !== undefined) {
|
|
451
|
+
const decodedScheme = unescape(parsed.scheme)
|
|
452
|
+
if (VALID_SCHEME.test(decodedScheme)) {
|
|
453
|
+
parsed.scheme = decodedScheme.toLowerCase()
|
|
454
|
+
} else {
|
|
455
|
+
parsed.error = parsed.error || MALFORMED_SCHEME_ERROR
|
|
456
|
+
malformedScheme = true
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
malformedPercentEncoding = hasMalformedComponentPercentEncoding(matches)
|
|
461
|
+
if (malformedPercentEncoding) {
|
|
462
|
+
parsed.error = parsed.error || 'URI contains malformed percent-encoding.'
|
|
463
|
+
}
|
|
464
|
+
|
|
316
465
|
// fix port number
|
|
317
466
|
if (isNaN(parsed.port)) {
|
|
318
467
|
parsed.port = matches[5]
|
|
@@ -327,9 +476,16 @@ function parseWithStatus (uri, opts) {
|
|
|
327
476
|
if (parsed.host) {
|
|
328
477
|
const ipv4result = isIPv4(parsed.host)
|
|
329
478
|
if (ipv4result === false) {
|
|
479
|
+
const bracketedIPLiteral = parsed.host[0] === '[' && parsed.host[parsed.host.length - 1] === ']'
|
|
330
480
|
const ipv6result = normalizeIPv6(parsed.host)
|
|
331
|
-
|
|
332
|
-
|
|
481
|
+
isIP = ipv6result.isIPV6 || ipv6result.isIPVFuture === true
|
|
482
|
+
malformedIPLiteral = bracketedIPLiteral && ipv6result.error === true
|
|
483
|
+
parsed.host = isIP ? ipv6result.host : ipv6result.host.toLowerCase()
|
|
484
|
+
|
|
485
|
+
if (malformedIPLiteral) {
|
|
486
|
+
parsed.error = parsed.error || 'URI host is malformed.'
|
|
487
|
+
malformedAuthorityOrPort = true
|
|
488
|
+
}
|
|
333
489
|
} else {
|
|
334
490
|
isIP = true
|
|
335
491
|
}
|
|
@@ -352,49 +508,38 @@ function parseWithStatus (uri, opts) {
|
|
|
352
508
|
// find scheme handler
|
|
353
509
|
const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme)
|
|
354
510
|
|
|
355
|
-
//
|
|
356
|
-
|
|
357
|
-
// if host component is a domain name
|
|
358
|
-
if (parsed.host && (options.domainHost || (schemeHandler && schemeHandler.domainHost)) && isIP === false && nonSimpleDomain(parsed.host)) {
|
|
359
|
-
// convert Unicode IDN -> ASCII IDN
|
|
360
|
-
try {
|
|
361
|
-
parsed.host = new URL('http://' + parsed.host).hostname
|
|
362
|
-
} catch (e) {
|
|
363
|
-
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
// convert IRI -> URI
|
|
367
|
-
}
|
|
511
|
+
// convert Unicode IDN -> ASCII IDN when the effective scheme uses domain hosts
|
|
512
|
+
malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP)
|
|
368
513
|
|
|
369
514
|
if (!schemeHandler || (schemeHandler && !schemeHandler.skipNormalize)) {
|
|
370
515
|
if (uri.indexOf('%') !== -1) {
|
|
371
|
-
if (parsed.
|
|
372
|
-
parsed.
|
|
373
|
-
|
|
374
|
-
if (parsed.host !== undefined) {
|
|
375
|
-
parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP)
|
|
516
|
+
if (parsed.host !== undefined && !malformedIPLiteral) {
|
|
517
|
+
const host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true)
|
|
518
|
+
parsed.host = reescapeHostDelimiters(host, isIP)
|
|
376
519
|
}
|
|
377
520
|
}
|
|
378
521
|
if (parsed.path) {
|
|
379
522
|
parsed.path = normalizePathEncoding(parsed.path)
|
|
380
523
|
}
|
|
524
|
+
if (parsed.query) {
|
|
525
|
+
parsed.query = normalizeQueryFragmentEncoding(parsed.query)
|
|
526
|
+
}
|
|
381
527
|
if (parsed.fragment) {
|
|
382
|
-
|
|
383
|
-
parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment))
|
|
384
|
-
} catch {
|
|
385
|
-
parsed.error = parsed.error || 'URI malformed'
|
|
386
|
-
}
|
|
528
|
+
parsed.fragment = normalizeQueryFragmentEncoding(parsed.fragment)
|
|
387
529
|
}
|
|
388
530
|
}
|
|
389
531
|
|
|
390
532
|
// perform scheme specific parsing
|
|
391
533
|
if (schemeHandler && schemeHandler.parse) {
|
|
392
534
|
schemeHandler.parse(parsed, options)
|
|
535
|
+
if (schemeHandler === SCHEMES.urn && parsed.nid === undefined) {
|
|
536
|
+
malformedSchemeSpecific = true
|
|
537
|
+
}
|
|
393
538
|
}
|
|
394
539
|
} else {
|
|
395
540
|
parsed.error = parsed.error || 'URI can not be parsed.'
|
|
396
541
|
}
|
|
397
|
-
return { parsed, malformedAuthorityOrPort }
|
|
542
|
+
return { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme }
|
|
398
543
|
}
|
|
399
544
|
|
|
400
545
|
/**
|
|
@@ -418,13 +563,17 @@ function normalizeString (uri, opts) {
|
|
|
418
563
|
/**
|
|
419
564
|
* @param {string} uri
|
|
420
565
|
* @param {import('./types/index').Options} [opts]
|
|
421
|
-
* @returns {{ normalized: string, malformedAuthorityOrPort: boolean }}
|
|
566
|
+
* @returns {{ normalized: string, malformedAuthorityOrPort: boolean, malformedPercentEncoding: boolean, malformedSchemeSpecific: boolean, malformedHost: boolean, malformedScheme: boolean }}
|
|
422
567
|
*/
|
|
423
568
|
function normalizeStringWithStatus (uri, opts) {
|
|
424
|
-
const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts)
|
|
569
|
+
const { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = parseWithStatus(uri, opts)
|
|
425
570
|
return {
|
|
426
|
-
normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
|
|
427
|
-
malformedAuthorityOrPort
|
|
571
|
+
normalized: malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? uri : serialize(parsed, opts),
|
|
572
|
+
malformedAuthorityOrPort,
|
|
573
|
+
malformedPercentEncoding,
|
|
574
|
+
malformedSchemeSpecific,
|
|
575
|
+
malformedHost,
|
|
576
|
+
malformedScheme
|
|
428
577
|
}
|
|
429
578
|
}
|
|
430
579
|
|
|
@@ -434,14 +583,18 @@ function normalizeStringWithStatus (uri, opts) {
|
|
|
434
583
|
* @returns {string|undefined}
|
|
435
584
|
*/
|
|
436
585
|
function normalizeComparableURI (uri, opts) {
|
|
437
|
-
if (typeof uri
|
|
438
|
-
|
|
439
|
-
return malformedAuthorityOrPort ? undefined : normalized
|
|
586
|
+
if (typeof uri !== 'string' && typeof uri !== 'object') {
|
|
587
|
+
return undefined
|
|
440
588
|
}
|
|
441
589
|
|
|
442
|
-
|
|
443
|
-
|
|
590
|
+
let value
|
|
591
|
+
try {
|
|
592
|
+
value = typeof uri === 'string' ? uri : serialize(uri, opts)
|
|
593
|
+
} catch {
|
|
594
|
+
return undefined
|
|
444
595
|
}
|
|
596
|
+
const { normalized, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = normalizeStringWithStatus(value, opts)
|
|
597
|
+
return malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? undefined : normalized
|
|
445
598
|
}
|
|
446
599
|
|
|
447
600
|
const fastUri = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { isUUID } = require('./utils')
|
|
4
|
-
const URN_REG =
|
|
4
|
+
const URN_REG = /^([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-./:;=@]|%[\da-f]{2})+)$/iu
|
|
5
5
|
|
|
6
6
|
const supportedSchemeNames = /** @type {const} */ (['http', 'https', 'ws',
|
|
7
7
|
'wss', 'urn', 'urn:uuid'])
|
|
@@ -113,9 +113,14 @@ function wsSerialize (wsComponent) {
|
|
|
113
113
|
|
|
114
114
|
// reconstruct path from resource name
|
|
115
115
|
if (wsComponent.resourceName) {
|
|
116
|
-
const
|
|
116
|
+
const queryIndex = wsComponent.resourceName.indexOf('?')
|
|
117
|
+
const path = queryIndex === -1
|
|
118
|
+
? wsComponent.resourceName
|
|
119
|
+
: wsComponent.resourceName.slice(0, queryIndex)
|
|
117
120
|
wsComponent.path = (path && path !== '/' ? path : undefined)
|
|
118
|
-
wsComponent.query =
|
|
121
|
+
wsComponent.query = queryIndex === -1
|
|
122
|
+
? undefined
|
|
123
|
+
: wsComponent.resourceName.slice(queryIndex + 1)
|
|
119
124
|
wsComponent.resourceName = undefined
|
|
120
125
|
}
|
|
121
126
|
|
|
@@ -132,7 +137,7 @@ function urnParse (urnComponent, options) {
|
|
|
132
137
|
return urnComponent
|
|
133
138
|
}
|
|
134
139
|
const matches = urnComponent.path.match(URN_REG)
|
|
135
|
-
if (matches) {
|
|
140
|
+
if (matches && matches[0] === urnComponent.path) {
|
|
136
141
|
const scheme = options.scheme || urnComponent.scheme || 'urn'
|
|
137
142
|
urnComponent.nid = matches[1].toLowerCase()
|
|
138
143
|
urnComponent.nss = matches[2]
|