@suveren/gateway 0.7.4 → 0.8.0
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/content/integrations/mollie.json +103 -28
- package/dist/control-plane/index.mjs +248 -58
- package/dist/mcp-server/http.mjs +577 -124
- package/dist/ui/assets/index-BFnSVa9N.js +110 -0
- package/dist/ui/assets/{index-CkWaRck1.css → index-BYVb_0oG.css} +1 -1
- package/dist/ui/index.html +2 -2
- package/node_modules/@hap/core/dist/index.d.mts +285 -13
- package/node_modules/@hap/core/dist/index.d.ts +285 -13
- package/node_modules/@hap/core/dist/index.js +281 -13
- package/node_modules/@hap/core/dist/index.mjs +266 -12
- package/node_modules/@hap/core/package.json +4 -2
- package/node_modules/@hap/core/src/did-key.ts +126 -0
- package/node_modules/@hap/core/src/frame.ts +115 -14
- package/node_modules/@hap/core/src/gatekeeper.ts +26 -0
- package/node_modules/@hap/core/src/identity.ts +21 -5
- package/node_modules/@hap/core/src/index.ts +3 -0
- package/node_modules/@hap/core/src/mandate.ts +207 -0
- package/node_modules/@hap/core/src/receipt.ts +74 -0
- package/node_modules/@hap/core/src/types.ts +87 -5
- package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/lib/accept.js +54 -0
- package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/lib/charset.js +10 -34
- package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/lib/encoding.js +9 -30
- package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/lib/language.js +15 -36
- package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/lib/mediaType.js +16 -134
- package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/node_modules/content-type/LICENSE +22 -0
- package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/node_modules/content-type/README.md +71 -0
- package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/node_modules/content-type/dist/index.d.ts +46 -0
- package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/node_modules/content-type/dist/index.js +176 -0
- package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/node_modules/content-type/dist/index.js.map +1 -0
- package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/node_modules/content-type/package.json +52 -0
- package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/package.json +16 -10
- package/node_modules/@types/node/README.md +1 -1
- package/node_modules/@types/node/buffer.buffer.d.ts +10 -5
- package/node_modules/@types/node/crypto.d.ts +2 -4
- package/node_modules/@types/node/dgram.d.ts +119 -4
- package/node_modules/@types/node/ffi.d.ts +1 -1
- package/node_modules/@types/node/fs/promises.d.ts +61 -65
- package/node_modules/@types/node/fs.d.ts +86 -76
- package/node_modules/@types/node/http.d.ts +17 -1
- package/node_modules/@types/node/http2.d.ts +12 -4
- package/node_modules/@types/node/index.d.ts +1 -0
- package/node_modules/@types/node/inspector.d.ts +2 -1
- package/node_modules/@types/node/net.d.ts +108 -16
- package/node_modules/@types/node/package.json +2 -2
- package/node_modules/@types/node/process.d.ts +52 -0
- package/node_modules/@types/node/quic.d.ts +246 -38
- package/node_modules/@types/node/sqlite.d.ts +6 -2
- package/node_modules/@types/node/stream/iter.d.ts +4 -4
- package/node_modules/@types/node/test.d.ts +36 -0
- package/node_modules/@types/node/tls.d.ts +24 -0
- package/node_modules/@types/node/ts5.6/buffer.buffer.d.ts +5 -0
- package/node_modules/@types/node/ts5.6/index.d.ts +1 -0
- package/node_modules/@types/node/ts5.7/index.d.ts +1 -0
- package/node_modules/@types/node/tty.d.ts +4 -3
- package/node_modules/@types/node/vfs.d.ts +210 -0
- package/node_modules/@types/node/vm.d.ts +1 -1
- package/node_modules/express-rate-limit/dist/index.cjs +6 -3
- package/node_modules/express-rate-limit/dist/index.d.cts +11 -0
- package/node_modules/express-rate-limit/dist/index.d.mts +11 -0
- package/node_modules/express-rate-limit/dist/index.d.ts +11 -0
- package/node_modules/express-rate-limit/dist/index.mjs +6 -3
- package/node_modules/express-rate-limit/{license.md → license} +7 -6
- package/node_modules/express-rate-limit/package.json +5 -5
- package/node_modules/express-rate-limit/readme.md +1 -0
- package/node_modules/fast-uri/index.js +215 -47
- package/node_modules/fast-uri/lib/schemes.js +9 -4
- package/node_modules/fast-uri/lib/utils.js +396 -92
- package/node_modules/fast-uri/package.json +1 -1
- package/node_modules/fast-uri/test/component-safe-serialization.test.js +163 -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 +124 -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/hono/dist/cjs/client/client.js +25 -11
- package/node_modules/hono/dist/cjs/client/utils.js +4 -1
- package/node_modules/hono/dist/cjs/context.js +4 -0
- package/node_modules/hono/dist/cjs/helper/accepts/accepts.js +36 -2
- package/node_modules/hono/dist/cjs/helper/ssg/ssg.js +1 -1
- package/node_modules/hono/dist/cjs/helper/ssg/utils.js +30 -10
- package/node_modules/hono/dist/cjs/jsx/dom/render.js +2 -0
- package/node_modules/hono/dist/cjs/middleware/cache/index.js +1 -1
- package/node_modules/hono/dist/cjs/middleware/cors/index.js +1 -1
- package/node_modules/hono/dist/cjs/middleware/csrf/index.js +1 -1
- package/node_modules/hono/dist/cjs/middleware/etag/digest.js +1 -1
- package/node_modules/hono/dist/cjs/middleware/etag/index.js +3 -3
- package/node_modules/hono/dist/cjs/middleware/pretty-json/index.js +3 -1
- package/node_modules/hono/dist/cjs/request.js +8 -4
- package/node_modules/hono/dist/cjs/router/linear-router/router.js +7 -2
- package/node_modules/hono/dist/cjs/router/pattern-router/router.js +3 -9
- package/node_modules/hono/dist/cjs/router/reg-exp-router/node.js +10 -3
- package/node_modules/hono/dist/cjs/router/reg-exp-router/router.js +47 -83
- package/node_modules/hono/dist/cjs/router/reg-exp-router/trie.js +2 -1
- package/node_modules/hono/dist/cjs/router/trie-router/node.js +46 -69
- package/node_modules/hono/dist/cjs/router/trie-router/router.js +3 -11
- package/node_modules/hono/dist/cjs/router/utils.js +27 -0
- package/node_modules/hono/dist/cjs/utils/body.js +15 -3
- package/node_modules/hono/dist/cjs/utils/cookie.js +1 -1
- package/node_modules/hono/dist/cjs/utils/ipaddr.js +5 -3
- package/node_modules/hono/dist/cjs/utils/stream.js +7 -1
- package/node_modules/hono/dist/cjs/utils/url.js +9 -1
- package/node_modules/hono/dist/client/client.js +25 -11
- package/node_modules/hono/dist/client/utils.js +4 -1
- package/node_modules/hono/dist/context.js +4 -0
- package/node_modules/hono/dist/helper/accepts/accepts.js +36 -2
- package/node_modules/hono/dist/helper/ssg/ssg.js +1 -1
- package/node_modules/hono/dist/helper/ssg/utils.js +30 -10
- package/node_modules/hono/dist/jsx/dom/render.js +2 -0
- package/node_modules/hono/dist/middleware/cache/index.js +1 -1
- package/node_modules/hono/dist/middleware/cors/index.js +1 -1
- package/node_modules/hono/dist/middleware/csrf/index.js +1 -1
- package/node_modules/hono/dist/middleware/etag/digest.js +1 -1
- package/node_modules/hono/dist/middleware/etag/index.js +3 -3
- package/node_modules/hono/dist/middleware/pretty-json/index.js +3 -1
- package/node_modules/hono/dist/request.js +8 -4
- package/node_modules/hono/dist/router/linear-router/router.js +7 -2
- package/node_modules/hono/dist/router/pattern-router/router.js +3 -9
- package/node_modules/hono/dist/router/reg-exp-router/node.js +6 -2
- package/node_modules/hono/dist/router/reg-exp-router/router.js +53 -84
- package/node_modules/hono/dist/router/reg-exp-router/trie.js +2 -1
- package/node_modules/hono/dist/router/trie-router/node.js +46 -69
- package/node_modules/hono/dist/router/trie-router/router.js +3 -11
- package/node_modules/hono/dist/router/utils.js +5 -0
- package/node_modules/hono/dist/types/context.d.ts +4 -0
- package/node_modules/hono/dist/types/router/reg-exp-router/node.d.ts +3 -0
- package/node_modules/hono/dist/types/router/trie-router/node.d.ts +1 -2
- package/node_modules/hono/dist/types/router/trie-router/router.d.ts +0 -1
- package/node_modules/hono/dist/types/router/utils.d.ts +1 -0
- package/node_modules/hono/dist/types/utils/url.d.ts +4 -0
- package/node_modules/hono/dist/utils/body.js +15 -3
- package/node_modules/hono/dist/utils/cookie.js +1 -1
- package/node_modules/hono/dist/utils/ipaddr.js +5 -3
- package/node_modules/hono/dist/utils/stream.js +7 -1
- package/node_modules/hono/dist/utils/url.js +9 -1
- package/node_modules/hono/package.json +1 -1
- package/node_modules/ip-address/README.md +92 -82
- package/node_modules/ip-address/dist/common.d.ts +20 -0
- package/node_modules/ip-address/dist/common.js +36 -0
- package/node_modules/ip-address/dist/common.js.map +1 -1
- package/node_modules/ip-address/dist/ipv4.d.ts +50 -0
- package/node_modules/ip-address/dist/ipv4.js +75 -0
- package/node_modules/ip-address/dist/ipv4.js.map +1 -1
- package/node_modules/ip-address/dist/ipv6.d.ts +79 -10
- package/node_modules/ip-address/dist/ipv6.js +120 -30
- package/node_modules/ip-address/dist/ipv6.js.map +1 -1
- package/node_modules/ip-address/dist/v4/constants.d.ts +12 -0
- package/node_modules/ip-address/dist/v4/constants.js +40 -1
- package/node_modules/ip-address/dist/v4/constants.js.map +1 -1
- package/node_modules/ip-address/dist/v6/constants.d.ts +14 -0
- package/node_modules/ip-address/dist/v6/constants.js +47 -1
- package/node_modules/ip-address/dist/v6/constants.js.map +1 -1
- package/node_modules/ip-address/package.json +1 -1
- package/node_modules/is-plain-object/README.md +39 -95
- package/node_modules/is-plain-object/dist/is-plain-object.js +0 -2
- package/node_modules/is-plain-object/is-plain-object.d.ts +6 -1
- package/node_modules/is-plain-object/package.json +8 -34
- package/node_modules/jose/dist/types/jwe/compact/decrypt.d.ts +7 -16
- package/node_modules/jose/dist/types/jwe/compact/encrypt.d.ts +10 -20
- package/node_modules/jose/dist/types/jwe/flattened/decrypt.d.ts +7 -16
- package/node_modules/jose/dist/types/jwe/flattened/encrypt.d.ts +16 -38
- package/node_modules/jose/dist/types/jwe/general/decrypt.d.ts +7 -16
- package/node_modules/jose/dist/types/jwe/general/encrypt.d.ts +19 -38
- package/node_modules/jose/dist/types/jwk/embedded.d.ts +3 -8
- package/node_modules/jose/dist/types/jwk/thumbprint.d.ts +5 -5
- package/node_modules/jose/dist/types/jwks/local.d.ts +6 -10
- package/node_modules/jose/dist/types/jwks/remote.d.ts +17 -28
- package/node_modules/jose/dist/types/jws/compact/sign.d.ts +5 -10
- package/node_modules/jose/dist/types/jws/compact/verify.d.ts +9 -18
- package/node_modules/jose/dist/types/jws/flattened/sign.d.ts +7 -16
- package/node_modules/jose/dist/types/jws/flattened/verify.d.ts +9 -18
- package/node_modules/jose/dist/types/jws/general/sign.d.ts +11 -21
- package/node_modules/jose/dist/types/jws/general/verify.d.ts +12 -21
- package/node_modules/jose/dist/types/jwt/decrypt.d.ts +10 -20
- package/node_modules/jose/dist/types/jwt/encrypt.d.ts +17 -29
- package/node_modules/jose/dist/types/jwt/sign.d.ts +12 -19
- package/node_modules/jose/dist/types/jwt/unsecured.d.ts +17 -28
- package/node_modules/jose/dist/types/jwt/verify.d.ts +9 -19
- package/node_modules/jose/dist/types/key/export.d.ts +4 -4
- package/node_modules/jose/dist/types/key/generate_key_pair.d.ts +6 -8
- package/node_modules/jose/dist/types/key/generate_secret.d.ts +4 -11
- package/node_modules/jose/dist/types/key/import.d.ts +10 -17
- package/node_modules/jose/dist/types/types.d.ts +48 -86
- package/node_modules/jose/dist/types/util/base64url.d.ts +2 -2
- package/node_modules/jose/dist/types/util/decode_jwt.d.ts +3 -10
- package/node_modules/jose/dist/types/util/decode_protected_header.d.ts +4 -4
- package/node_modules/jose/dist/types/util/errors.d.ts +26 -53
- package/node_modules/jose/dist/webapi/index.js +70 -32
- package/node_modules/jose/dist/webapi/jwe/compact/decrypt.js +7 -8
- package/node_modules/jose/dist/webapi/jwe/compact/encrypt.js +42 -26
- package/node_modules/jose/dist/webapi/jwe/flattened/decrypt.js +14 -10
- package/node_modules/jose/dist/webapi/jwe/flattened/encrypt.js +53 -71
- package/node_modules/jose/dist/webapi/jwe/general/decrypt.js +38 -49
- package/node_modules/jose/dist/webapi/jwe/general/encrypt.js +121 -158
- package/node_modules/jose/dist/webapi/jwk/embedded.js +30 -18
- package/node_modules/jose/dist/webapi/jwk/thumbprint.js +54 -64
- package/node_modules/jose/dist/webapi/jwks/local.js +49 -74
- package/node_modules/jose/dist/webapi/jwks/remote.js +91 -160
- package/node_modules/jose/dist/webapi/jws/compact/sign.js +21 -20
- package/node_modules/jose/dist/webapi/jws/compact/verify.js +7 -8
- package/node_modules/jose/dist/webapi/jws/flattened/sign.js +29 -30
- package/node_modules/jose/dist/webapi/jws/flattened/verify.js +21 -23
- package/node_modules/jose/dist/webapi/jws/general/sign.js +61 -70
- package/node_modules/jose/dist/webapi/jws/general/verify.js +47 -41
- package/node_modules/jose/dist/webapi/jwt/decrypt.js +13 -22
- package/node_modules/jose/dist/webapi/jwt/encrypt.js +58 -100
- package/node_modules/jose/dist/webapi/jwt/sign.js +18 -50
- package/node_modules/jose/dist/webapi/jwt/unsecured.js +34 -63
- package/node_modules/jose/dist/webapi/jwt/verify.js +12 -14
- package/node_modules/jose/dist/webapi/key/export.js +32 -37
- package/node_modules/jose/dist/webapi/key/generate_key_pair.js +40 -44
- package/node_modules/jose/dist/webapi/key/generate_secret.js +35 -39
- package/node_modules/jose/dist/webapi/key/import.js +52 -52
- package/node_modules/jose/dist/webapi/lib/asn1.js +130 -164
- package/node_modules/jose/dist/webapi/lib/base64.js +18 -20
- package/node_modules/jose/dist/webapi/lib/buffer_utils.js +34 -38
- package/node_modules/jose/dist/webapi/lib/content_encryption.js +79 -123
- package/node_modules/jose/dist/webapi/lib/crypto_key.js +24 -25
- package/node_modules/jose/dist/webapi/lib/deflate.js +46 -40
- package/node_modules/jose/dist/webapi/lib/helpers.js +40 -37
- package/node_modules/jose/dist/webapi/lib/invalid_key_input.js +10 -24
- package/node_modules/jose/dist/webapi/lib/is_key_like.js +17 -15
- package/node_modules/jose/dist/webapi/lib/jwe_algorithms.js +106 -93
- package/node_modules/jose/dist/webapi/lib/jwe_decrypt.js +210 -176
- package/node_modules/jose/dist/webapi/lib/jwe_encrypt.js +105 -107
- package/node_modules/jose/dist/webapi/lib/jwk_metadata.js +19 -0
- package/node_modules/jose/dist/webapi/lib/jwk_to_key.js +9 -16
- package/node_modules/jose/dist/webapi/lib/jws_algorithms.js +62 -61
- package/node_modules/jose/dist/webapi/lib/jws_sign.js +58 -72
- package/node_modules/jose/dist/webapi/lib/jws_verify.js +90 -103
- package/node_modules/jose/dist/webapi/lib/jwt_claims_set.js +134 -185
- package/node_modules/jose/dist/webapi/lib/key.js +84 -121
- package/node_modules/jose/dist/webapi/lib/key_algorithm.js +13 -8
- package/node_modules/jose/dist/webapi/lib/key_descriptor.js +8 -6
- package/node_modules/jose/dist/webapi/lib/key_management.js +200 -225
- package/node_modules/jose/dist/webapi/lib/key_options.js +8 -0
- package/node_modules/jose/dist/webapi/lib/options.js +57 -44
- package/node_modules/jose/dist/webapi/lib/signing.js +18 -22
- package/node_modules/jose/dist/webapi/lib/type_checks.js +28 -33
- package/node_modules/jose/dist/webapi/util/base64url.js +26 -35
- package/node_modules/jose/dist/webapi/util/decode_jwt.js +32 -31
- package/node_modules/jose/dist/webapi/util/decode_protected_header.js +18 -23
- package/node_modules/jose/dist/webapi/util/errors.js +94 -84
- package/node_modules/jose/package.json +17 -81
- package/package.json +2 -2
- package/profiles/calendar/0.5.profile.json +190 -0
- package/profiles/charge/0.5.profile.json +210 -0
- package/profiles/customers/0.7.profile.json +157 -0
- package/profiles/deploy/0.9.profile.json +176 -0
- package/profiles/email/0.6.profile.json +208 -0
- package/profiles/index.json +9 -1
- package/profiles/publish/0.5.profile.json +186 -0
- package/profiles/purchase/0.5.profile.json +231 -0
- package/profiles/records/0.5.profile.json +117 -0
- package/dist/ui/assets/index-0Q2eNytX.js +0 -110
- package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/HISTORY.md +0 -114
|
@@ -6,6 +6,9 @@ const isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\d
|
|
|
6
6
|
/** @type {(value: string) => boolean} */
|
|
7
7
|
const isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u)
|
|
8
8
|
|
|
9
|
+
/** @type {(value: string) => boolean} */
|
|
10
|
+
const isPort = RegExp.prototype.test.bind(/^\d*$/u)
|
|
11
|
+
|
|
9
12
|
/** @type {(value: string) => boolean} */
|
|
10
13
|
const isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu)
|
|
11
14
|
|
|
@@ -13,7 +16,36 @@ const isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu)
|
|
|
13
16
|
const isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu)
|
|
14
17
|
|
|
15
18
|
/** @type {(value: string) => boolean} */
|
|
16
|
-
const isPathCharacter = RegExp.prototype.test.bind(/^[
|
|
19
|
+
const isPathCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/]$/u)
|
|
20
|
+
|
|
21
|
+
/** @type {(value: string) => boolean} */
|
|
22
|
+
const isQueryFragmentCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/?]$/u)
|
|
23
|
+
|
|
24
|
+
/** @type {(value: string) => boolean} */
|
|
25
|
+
const isUserinfoCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:]$/u)
|
|
26
|
+
|
|
27
|
+
const BYTE_HEX = new Array(256)
|
|
28
|
+
{
|
|
29
|
+
const HEX_DIGITS = '0123456789ABCDEF'
|
|
30
|
+
for (let i = 0; i < 256; i++) {
|
|
31
|
+
BYTE_HEX[i] = '%' + HEX_DIGITS[i >> 4] + HEX_DIGITS[i & 0xF]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function percentEncodeNonAscii (cp) {
|
|
35
|
+
if (cp < 0x800) {
|
|
36
|
+
return BYTE_HEX[0xC0 | (cp >> 6)] +
|
|
37
|
+
BYTE_HEX[0x80 | (cp & 0x3F)]
|
|
38
|
+
}
|
|
39
|
+
if (cp < 0x10000) {
|
|
40
|
+
return BYTE_HEX[0xE0 | (cp >> 12)] +
|
|
41
|
+
BYTE_HEX[0x80 | ((cp >> 6) & 0x3F)] +
|
|
42
|
+
BYTE_HEX[0x80 | (cp & 0x3F)]
|
|
43
|
+
}
|
|
44
|
+
return BYTE_HEX[0xF0 | (cp >> 18)] +
|
|
45
|
+
BYTE_HEX[0x80 | ((cp >> 12) & 0x3F)] +
|
|
46
|
+
BYTE_HEX[0x80 | ((cp >> 6) & 0x3F)] +
|
|
47
|
+
BYTE_HEX[0x80 | (cp & 0x3F)]
|
|
48
|
+
}
|
|
17
49
|
|
|
18
50
|
/**
|
|
19
51
|
* @param {Array<string>} input
|
|
@@ -46,12 +78,14 @@ function stringArrayToHexStripped (input) {
|
|
|
46
78
|
return acc
|
|
47
79
|
}
|
|
48
80
|
|
|
49
|
-
/**
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
81
|
+
/** @type {(value: string) => boolean} */
|
|
82
|
+
const isHextet = RegExp.prototype.test.bind(/^[\dA-Fa-f]{1,4}$/)
|
|
83
|
+
|
|
84
|
+
/** @type {(value: string) => boolean} */
|
|
85
|
+
const isIPvFuture = RegExp.prototype.test.bind(/^[vV][\dA-Fa-f]+\.[A-Za-z\d\-._~!$&'()*+,;=:]+$/)
|
|
86
|
+
|
|
87
|
+
/** @type {(value: string) => boolean} */
|
|
88
|
+
const isZoneCharacter = RegExp.prototype.test.bind(/^[A-Za-z\d\-._~]$/)
|
|
55
89
|
|
|
56
90
|
/**
|
|
57
91
|
* @param {string} value
|
|
@@ -60,88 +94,104 @@ function stringArrayToHexStripped (input) {
|
|
|
60
94
|
const nonSimpleDomain = RegExp.prototype.test.bind(/[^!"$&'()*+,\-.;=_`a-z{}~]/u)
|
|
61
95
|
|
|
62
96
|
/**
|
|
63
|
-
* @param {
|
|
97
|
+
* @param {string} zone
|
|
64
98
|
* @returns {boolean}
|
|
65
99
|
*/
|
|
66
|
-
function
|
|
67
|
-
|
|
100
|
+
function isZoneIdentifier (zone) {
|
|
101
|
+
if (zone.length === 0) return false
|
|
102
|
+
|
|
103
|
+
for (let i = 0; i < zone.length; i++) {
|
|
104
|
+
if (isZoneCharacter(zone[i])) continue
|
|
105
|
+
if (zone[i] === '%' && i + 2 < zone.length && isHexPair(zone.slice(i + 1, i + 3))) {
|
|
106
|
+
i += 2
|
|
107
|
+
continue
|
|
108
|
+
}
|
|
109
|
+
return false
|
|
110
|
+
}
|
|
111
|
+
|
|
68
112
|
return true
|
|
69
113
|
}
|
|
70
114
|
|
|
71
115
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
* @
|
|
116
|
+
* Compresses the longest run of zero hextets to "::" per RFC 5952. A run of a
|
|
117
|
+
* single zero hextet is left uncompressed. On ties the leftmost run wins.
|
|
118
|
+
*
|
|
119
|
+
* @param {string[]} hextets
|
|
120
|
+
* @returns {string}
|
|
76
121
|
*/
|
|
77
|
-
function
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
122
|
+
function compressIPv6ZeroRun (hextets) {
|
|
123
|
+
let bestStart = -1
|
|
124
|
+
let bestLength = 0
|
|
125
|
+
let runStart = -1
|
|
126
|
+
let runLength = 0
|
|
127
|
+
for (let i = 0; i < hextets.length; i++) {
|
|
128
|
+
if (hextets[i] === '0') {
|
|
129
|
+
if (runStart === -1) runStart = i
|
|
130
|
+
runLength++
|
|
131
|
+
if (runLength > bestLength) {
|
|
132
|
+
bestLength = runLength
|
|
133
|
+
bestStart = runStart
|
|
134
|
+
}
|
|
82
135
|
} else {
|
|
83
|
-
|
|
84
|
-
|
|
136
|
+
runStart = -1
|
|
137
|
+
runLength = 0
|
|
85
138
|
}
|
|
86
|
-
buffer.length = 0
|
|
87
139
|
}
|
|
88
|
-
|
|
140
|
+
|
|
141
|
+
if (bestLength < 2) return hextets.join(':')
|
|
142
|
+
|
|
143
|
+
const head = hextets.slice(0, bestStart).join(':')
|
|
144
|
+
const tail = hextets.slice(bestStart + bestLength).join(':')
|
|
145
|
+
return head + '::' + tail
|
|
89
146
|
}
|
|
90
147
|
|
|
91
148
|
/**
|
|
149
|
+
* Validates an IPv6 address against the alternatives in RFC 3986 section
|
|
150
|
+
* 3.2.2 and returns the same address with leading hextet zeroes removed.
|
|
151
|
+
* An embedded IPv4 address counts as two hextets and is only valid at the end.
|
|
152
|
+
*
|
|
92
153
|
* @param {string} input
|
|
93
|
-
* @returns {
|
|
154
|
+
* @returns {string|undefined}
|
|
94
155
|
*/
|
|
95
|
-
function
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
let consume = consumeHextets
|
|
156
|
+
function normalizeIPv6Address (input) {
|
|
157
|
+
const compression = input.indexOf('::')
|
|
158
|
+
if (compression !== -1 && input.indexOf('::', compression + 1) !== -1) return undefined
|
|
159
|
+
|
|
160
|
+
const left = compression === -1 ? input.split(':') : input.slice(0, compression).split(':')
|
|
161
|
+
const right = compression === -1 ? [] : input.slice(compression + 2).split(':')
|
|
162
|
+
if (compression !== -1) {
|
|
163
|
+
if (left.length === 1 && left[0] === '') left.length = 0
|
|
164
|
+
if (right.length === 1 && right[0] === '') right.length = 0
|
|
165
|
+
}
|
|
106
166
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
if (
|
|
115
|
-
|
|
116
|
-
// not valid
|
|
117
|
-
output.error = true
|
|
118
|
-
break
|
|
119
|
-
}
|
|
120
|
-
if (i > 0 && input[i - 1] === ':') {
|
|
121
|
-
endipv6Encountered = true
|
|
122
|
-
}
|
|
123
|
-
address.push(':')
|
|
124
|
-
continue
|
|
125
|
-
} else if (cursor === '%') {
|
|
126
|
-
if (!consume(buffer, address, output)) { break }
|
|
127
|
-
// switch to zone detection
|
|
128
|
-
consume = consumeIsZone
|
|
129
|
-
} else {
|
|
130
|
-
buffer.push(cursor)
|
|
167
|
+
const parts = left.concat(right)
|
|
168
|
+
let hextetCount = 0
|
|
169
|
+
for (let i = 0; i < parts.length; i++) {
|
|
170
|
+
const part = parts[i]
|
|
171
|
+
if (part === '') return undefined
|
|
172
|
+
|
|
173
|
+
if (part.indexOf('.') !== -1) {
|
|
174
|
+
if (i !== parts.length - 1 || (compression !== -1 && right.length === 0) || !isIPv4(part)) return undefined
|
|
175
|
+
hextetCount += 2
|
|
131
176
|
continue
|
|
132
177
|
}
|
|
178
|
+
|
|
179
|
+
if (!isHextet(part)) return undefined
|
|
180
|
+
parts[i] = parseInt(part, 16).toString(16)
|
|
181
|
+
hextetCount++
|
|
133
182
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
address.push(buffer.join(''))
|
|
139
|
-
} else {
|
|
140
|
-
address.push(stringArrayToHexStripped(buffer))
|
|
141
|
-
}
|
|
183
|
+
|
|
184
|
+
if (compression === -1) {
|
|
185
|
+
if (hextetCount !== 8) return undefined
|
|
186
|
+
return compressIPv6ZeroRun(parts)
|
|
142
187
|
}
|
|
143
|
-
|
|
144
|
-
|
|
188
|
+
if (hextetCount >= 8) return undefined
|
|
189
|
+
|
|
190
|
+
// expand "::" then re-compress the longest run for a canonical result
|
|
191
|
+
const expanded = parts.slice(0, left.length)
|
|
192
|
+
for (let i = hextetCount; i < 8; i++) expanded.push('0')
|
|
193
|
+
for (let i = left.length; i < parts.length; i++) expanded.push(parts[i])
|
|
194
|
+
return compressIPv6ZeroRun(expanded)
|
|
145
195
|
}
|
|
146
196
|
|
|
147
197
|
/**
|
|
@@ -149,26 +199,49 @@ function getIPV6 (input) {
|
|
|
149
199
|
* @property {string} host - The normalized host.
|
|
150
200
|
* @property {string} [escapedHost] - The escaped host.
|
|
151
201
|
* @property {boolean} isIPV6 - Indicates if the host is an IPv6 address.
|
|
202
|
+
* @property {boolean} [isIPVFuture] - Indicates if the host is an IPvFuture literal.
|
|
203
|
+
* @property {boolean} [error] - Indicates if a bracketed IP literal is malformed.
|
|
152
204
|
*/
|
|
153
205
|
|
|
154
206
|
/**
|
|
207
|
+
* Validates and normalizes a bracketed IP literal. Raw zone separators remain
|
|
208
|
+
* accepted for backwards compatibility, while encoded separators and zone
|
|
209
|
+
* contents follow RFC 6874.
|
|
210
|
+
*
|
|
155
211
|
* @param {string} host
|
|
156
212
|
* @returns {NormalizeIPv6Result}
|
|
157
213
|
*/
|
|
158
214
|
function normalizeIPv6 (host) {
|
|
159
|
-
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
215
|
+
const bracketed = host[0] === '[' && host[host.length - 1] === ']'
|
|
216
|
+
const hasBracket = host[0] === '[' || host[host.length - 1] === ']'
|
|
217
|
+
if (hasBracket && !bracketed) return { host, isIPV6: false, error: true }
|
|
218
|
+
|
|
219
|
+
let input = bracketed ? host.slice(1, -1) : host
|
|
220
|
+
if (bracketed && isIPvFuture(input)) {
|
|
221
|
+
input = input.toLowerCase()
|
|
222
|
+
return { host: `[${input}]`, escapedHost: input, isIPV6: false, isIPVFuture: true }
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (findToken(input, ':') < 2) {
|
|
226
|
+
return { host, isIPV6: false, error: bracketed }
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
let zoneIdentifier = ''
|
|
230
|
+
const zoneSeparator = input.indexOf('%')
|
|
231
|
+
if (zoneSeparator !== -1) {
|
|
232
|
+
const separatorLength = input.slice(zoneSeparator, zoneSeparator + 3).toLowerCase() === '%25' ? 3 : 1
|
|
233
|
+
zoneIdentifier = input.slice(zoneSeparator + separatorLength)
|
|
234
|
+
if (!isZoneIdentifier(zoneIdentifier)) return { host, isIPV6: false, error: true }
|
|
235
|
+
input = input.slice(0, zoneSeparator)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const address = normalizeIPv6Address(input)
|
|
239
|
+
if (address === undefined) return { host, isIPV6: false, error: true }
|
|
240
|
+
|
|
241
|
+
return {
|
|
242
|
+
host: address + (zoneIdentifier ? '%' + zoneIdentifier : ''),
|
|
243
|
+
escapedHost: address + (zoneIdentifier ? '%25' + zoneIdentifier : ''),
|
|
244
|
+
isIPV6: true
|
|
172
245
|
}
|
|
173
246
|
}
|
|
174
247
|
|
|
@@ -294,7 +367,7 @@ function reescapeHostDelimiters (host, isIP) {
|
|
|
294
367
|
|
|
295
368
|
/**
|
|
296
369
|
* Normalizes percent escapes and optionally decodes only unreserved ASCII bytes.
|
|
297
|
-
* Reserved delimiters such as `%2F`
|
|
370
|
+
* Reserved delimiters such as `%2F` stay escaped; `%2E` is unreserved.
|
|
298
371
|
*
|
|
299
372
|
* @param {string} input
|
|
300
373
|
* @param {boolean} [decodeUnreserved=false]
|
|
@@ -343,7 +416,8 @@ function normalizePathEncoding (input) {
|
|
|
343
416
|
let output = ''
|
|
344
417
|
|
|
345
418
|
for (let i = 0; i < input.length; i++) {
|
|
346
|
-
|
|
419
|
+
const ch = input[i]
|
|
420
|
+
if (ch === '%' && i + 2 < input.length) {
|
|
347
421
|
const hex = input.slice(i + 1, i + 3)
|
|
348
422
|
if (isHexPair(hex)) {
|
|
349
423
|
const normalizedHex = hex.toUpperCase()
|
|
@@ -360,10 +434,225 @@ function normalizePathEncoding (input) {
|
|
|
360
434
|
}
|
|
361
435
|
}
|
|
362
436
|
|
|
363
|
-
if (isPathCharacter(
|
|
364
|
-
output +=
|
|
437
|
+
if (isPathCharacter(ch)) {
|
|
438
|
+
output += ch
|
|
439
|
+
} else {
|
|
440
|
+
const code = input.charCodeAt(i)
|
|
441
|
+
if (code < 0x80) {
|
|
442
|
+
output += isEscapeSafe(code) ? ch : BYTE_HEX[code]
|
|
443
|
+
} else if (code < 0xD800 || code > 0xDFFF) {
|
|
444
|
+
output += percentEncodeNonAscii(code)
|
|
445
|
+
} else if (code <= 0xDBFF && i + 1 < input.length) {
|
|
446
|
+
const low = input.charCodeAt(i + 1)
|
|
447
|
+
if (low >= 0xDC00 && low <= 0xDFFF) {
|
|
448
|
+
output += percentEncodeNonAscii(0x10000 + ((code - 0xD800) << 10) + (low - 0xDC00))
|
|
449
|
+
i++
|
|
450
|
+
} else {
|
|
451
|
+
output += percentEncodeNonAscii(0xFFFD)
|
|
452
|
+
}
|
|
453
|
+
} else {
|
|
454
|
+
output += percentEncodeNonAscii(0xFFFD)
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
return output
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Serializes a path without rewriting reserved data. Raw RFC 3986 path
|
|
464
|
+
* characters remain literal, valid escapes are preserved and uppercased, and
|
|
465
|
+
* everything else is UTF-8 percent-encoded. In a path-noscheme, a colon in the
|
|
466
|
+
* first segment must be escaped so the result cannot be parsed as a scheme.
|
|
467
|
+
*
|
|
468
|
+
* @param {string} input
|
|
469
|
+
* @param {boolean} [pathNoScheme=false]
|
|
470
|
+
* @returns {string}
|
|
471
|
+
*/
|
|
472
|
+
function serializePathEncoding (input, pathNoScheme = false) {
|
|
473
|
+
let output = ''
|
|
474
|
+
let firstSegment = pathNoScheme && input[0] !== '/'
|
|
475
|
+
|
|
476
|
+
for (let i = 0; i < input.length; i++) {
|
|
477
|
+
const ch = input[i]
|
|
478
|
+
if (ch === '%' && i + 2 < input.length) {
|
|
479
|
+
const hex = input.slice(i + 1, i + 3)
|
|
480
|
+
if (isHexPair(hex)) {
|
|
481
|
+
output += '%' + hex.toUpperCase()
|
|
482
|
+
i += 2
|
|
483
|
+
continue
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
if (ch === '/') {
|
|
488
|
+
firstSegment = false
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
if (isPathCharacter(ch) && (ch !== ':' || !firstSegment)) {
|
|
492
|
+
output += ch
|
|
493
|
+
} else {
|
|
494
|
+
const code = input.charCodeAt(i)
|
|
495
|
+
if (code < 0x80) {
|
|
496
|
+
output += BYTE_HEX[code]
|
|
497
|
+
} else if (code < 0xD800 || code > 0xDFFF) {
|
|
498
|
+
output += percentEncodeNonAscii(code)
|
|
499
|
+
} else if (code <= 0xDBFF && i + 1 < input.length) {
|
|
500
|
+
const low = input.charCodeAt(i + 1)
|
|
501
|
+
if (low >= 0xDC00 && low <= 0xDFFF) {
|
|
502
|
+
output += percentEncodeNonAscii(0x10000 + ((code - 0xD800) << 10) + (low - 0xDC00))
|
|
503
|
+
i++
|
|
504
|
+
} else {
|
|
505
|
+
output += percentEncodeNonAscii(0xFFFD)
|
|
506
|
+
}
|
|
507
|
+
} else {
|
|
508
|
+
output += percentEncodeNonAscii(0xFFFD)
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
return output
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Percent-encodes a URI component using its RFC 3986 literal character set.
|
|
518
|
+
* Existing valid escapes are preserved and normalized to uppercase hex.
|
|
519
|
+
*
|
|
520
|
+
* @param {string} input
|
|
521
|
+
* @param {(value: string) => boolean} isAllowed
|
|
522
|
+
* @returns {string}
|
|
523
|
+
*/
|
|
524
|
+
function encodeComponent (input, isAllowed) {
|
|
525
|
+
let output = ''
|
|
526
|
+
|
|
527
|
+
for (let i = 0; i < input.length; i++) {
|
|
528
|
+
const ch = input[i]
|
|
529
|
+
if (ch === '%' && i + 2 < input.length) {
|
|
530
|
+
const hex = input.slice(i + 1, i + 3)
|
|
531
|
+
if (isHexPair(hex)) {
|
|
532
|
+
output += '%' + hex.toUpperCase()
|
|
533
|
+
i += 2
|
|
534
|
+
continue
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
if (isAllowed(ch)) {
|
|
539
|
+
output += ch
|
|
540
|
+
} else {
|
|
541
|
+
const code = input.charCodeAt(i)
|
|
542
|
+
if (code < 0x80) {
|
|
543
|
+
output += BYTE_HEX[code]
|
|
544
|
+
} else if (code < 0xD800 || code > 0xDFFF) {
|
|
545
|
+
output += percentEncodeNonAscii(code)
|
|
546
|
+
} else if (code <= 0xDBFF && i + 1 < input.length) {
|
|
547
|
+
const low = input.charCodeAt(i + 1)
|
|
548
|
+
if (low >= 0xDC00 && low <= 0xDFFF) {
|
|
549
|
+
output += percentEncodeNonAscii(0x10000 + ((code - 0xD800) << 10) + (low - 0xDC00))
|
|
550
|
+
i++
|
|
551
|
+
} else {
|
|
552
|
+
output += percentEncodeNonAscii(0xFFFD)
|
|
553
|
+
}
|
|
554
|
+
} else {
|
|
555
|
+
output += percentEncodeNonAscii(0xFFFD)
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
return output
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Encodes userinfo while preserving its RFC 3986 §3.2.1 literal characters.
|
|
565
|
+
* In particular, authority delimiters such as `@`, `/`, `?`, and `#` are data.
|
|
566
|
+
*
|
|
567
|
+
* @param {string} input
|
|
568
|
+
* @returns {string}
|
|
569
|
+
*/
|
|
570
|
+
function encodeUserinfo (input) {
|
|
571
|
+
return encodeComponent(input, isUserinfoCharacter)
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Encodes query data using the RFC 3986 §3.4 grammar. A literal `#` must be
|
|
576
|
+
* escaped because it would otherwise begin the fragment component.
|
|
577
|
+
*
|
|
578
|
+
* @param {string} input
|
|
579
|
+
* @returns {string}
|
|
580
|
+
*/
|
|
581
|
+
function encodeQuery (input) {
|
|
582
|
+
return encodeComponent(input, isQueryFragmentCharacter)
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* Encodes fragment data using the RFC 3986 §3.5 grammar.
|
|
587
|
+
*
|
|
588
|
+
* @param {string} input
|
|
589
|
+
* @returns {string}
|
|
590
|
+
*/
|
|
591
|
+
function encodeFragment (input) {
|
|
592
|
+
return encodeComponent(input, isQueryFragmentCharacter)
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
function isEscapeSafe (cp) {
|
|
596
|
+
return (
|
|
597
|
+
(cp >= 0x30 && cp <= 0x39) ||
|
|
598
|
+
(cp >= 0x41 && cp <= 0x5A) ||
|
|
599
|
+
(cp >= 0x61 && cp <= 0x7A) ||
|
|
600
|
+
cp === 0x2A || cp === 0x2B || cp === 0x2D || cp === 0x2E ||
|
|
601
|
+
cp === 0x2F || cp === 0x40 || cp === 0x5F
|
|
602
|
+
)
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* Normalizes the percent-encoding of a query or fragment component.
|
|
607
|
+
*
|
|
608
|
+
* Like `normalizePathEncoding`, but uses the query/fragment character set
|
|
609
|
+
* (which additionally allows `?`) and decodes `.` since it has no dot-segment
|
|
610
|
+
* meaning outside of a path.
|
|
611
|
+
*
|
|
612
|
+
* @param {string} input
|
|
613
|
+
* @returns {string}
|
|
614
|
+
*/
|
|
615
|
+
function normalizeQueryFragmentEncoding (input) {
|
|
616
|
+
let output = ''
|
|
617
|
+
|
|
618
|
+
for (let i = 0; i < input.length; i++) {
|
|
619
|
+
const ch = input[i]
|
|
620
|
+
if (ch === '%' && i + 2 < input.length) {
|
|
621
|
+
const hex = input.slice(i + 1, i + 3)
|
|
622
|
+
if (isHexPair(hex)) {
|
|
623
|
+
const normalizedHex = hex.toUpperCase()
|
|
624
|
+
const decoded = String.fromCharCode(parseInt(normalizedHex, 16))
|
|
625
|
+
|
|
626
|
+
if (isUnreserved(decoded)) {
|
|
627
|
+
output += decoded
|
|
628
|
+
} else {
|
|
629
|
+
output += '%' + normalizedHex
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
i += 2
|
|
633
|
+
continue
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
if (isQueryFragmentCharacter(ch)) {
|
|
638
|
+
output += ch
|
|
365
639
|
} else {
|
|
366
|
-
|
|
640
|
+
const code = input.charCodeAt(i)
|
|
641
|
+
if (code < 0x80) {
|
|
642
|
+
output += isEscapeSafe(code) ? ch : BYTE_HEX[code]
|
|
643
|
+
} else if (code < 0xD800 || code > 0xDFFF) {
|
|
644
|
+
output += percentEncodeNonAscii(code)
|
|
645
|
+
} else if (code <= 0xDBFF && i + 1 < input.length) {
|
|
646
|
+
const low = input.charCodeAt(i + 1)
|
|
647
|
+
if (low >= 0xDC00 && low <= 0xDFFF) {
|
|
648
|
+
output += percentEncodeNonAscii(0x10000 + ((code - 0xD800) << 10) + (low - 0xDC00))
|
|
649
|
+
i++
|
|
650
|
+
} else {
|
|
651
|
+
output += percentEncodeNonAscii(0xFFFD)
|
|
652
|
+
}
|
|
653
|
+
} else {
|
|
654
|
+
output += percentEncodeNonAscii(0xFFFD)
|
|
655
|
+
}
|
|
367
656
|
}
|
|
368
657
|
}
|
|
369
658
|
|
|
@@ -403,15 +692,21 @@ function recomposeAuthority (component) {
|
|
|
403
692
|
const uriTokens = []
|
|
404
693
|
|
|
405
694
|
if (component.userinfo !== undefined) {
|
|
406
|
-
uriTokens.push(component.userinfo)
|
|
695
|
+
uriTokens.push(encodeUserinfo(component.userinfo))
|
|
407
696
|
uriTokens.push('@')
|
|
408
697
|
}
|
|
409
698
|
|
|
410
699
|
if (component.host !== undefined) {
|
|
411
|
-
let host =
|
|
700
|
+
let host = component.host
|
|
412
701
|
if (!isIPv4(host)) {
|
|
413
|
-
|
|
414
|
-
if (ipV6res.isIPV6
|
|
702
|
+
let ipV6res = normalizeIPv6(host)
|
|
703
|
+
if (ipV6res.isIPV6 !== true && ipV6res.isIPVFuture !== true) {
|
|
704
|
+
// Decode only unreserved bytes, once. In particular, keep %25 encoded
|
|
705
|
+
// so it cannot introduce a second escape during recomposition.
|
|
706
|
+
host = normalizePercentEncoding(host, true)
|
|
707
|
+
ipV6res = normalizeIPv6(host)
|
|
708
|
+
}
|
|
709
|
+
if (ipV6res.isIPV6 === true || ipV6res.isIPVFuture === true) {
|
|
415
710
|
host = `[${ipV6res.escapedHost}]`
|
|
416
711
|
} else {
|
|
417
712
|
host = reescapeHostDelimiters(host, false)
|
|
@@ -421,8 +716,12 @@ function recomposeAuthority (component) {
|
|
|
421
716
|
}
|
|
422
717
|
|
|
423
718
|
if (typeof component.port === 'number' || typeof component.port === 'string') {
|
|
719
|
+
const port = String(component.port)
|
|
720
|
+
if (!isPort(port)) {
|
|
721
|
+
throw new TypeError('URI port is malformed.')
|
|
722
|
+
}
|
|
424
723
|
uriTokens.push(':')
|
|
425
|
-
uriTokens.push(
|
|
724
|
+
uriTokens.push(port)
|
|
426
725
|
}
|
|
427
726
|
|
|
428
727
|
return uriTokens.length ? uriTokens.join('') : undefined
|
|
@@ -434,6 +733,11 @@ module.exports = {
|
|
|
434
733
|
reescapeHostDelimiters,
|
|
435
734
|
normalizePercentEncoding,
|
|
436
735
|
normalizePathEncoding,
|
|
736
|
+
serializePathEncoding,
|
|
737
|
+
normalizeQueryFragmentEncoding,
|
|
738
|
+
encodeUserinfo,
|
|
739
|
+
encodeQuery,
|
|
740
|
+
encodeFragment,
|
|
437
741
|
escapePreservingEscapes,
|
|
438
742
|
removeDotSegments,
|
|
439
743
|
isIPv4,
|