fast-uri 2.4.0 → 3.0.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.
@@ -17,6 +17,7 @@ on:
17
17
 
18
18
  jobs:
19
19
  test:
20
- uses: fastify/workflows/.github/workflows/plugins-ci.yml@v3
20
+ uses: fastify/workflows/.github/workflows/plugins-ci.yml@v4.2.0
21
21
  with:
22
22
  license-check: true
23
+ node-versions: '["16", "18", "20"]'
@@ -17,4 +17,4 @@ on:
17
17
 
18
18
  jobs:
19
19
  test:
20
- uses: fastify/workflows/.github/workflows/plugins-ci-package-manager.yml@v3
20
+ uses: fastify/workflows/.github/workflows/plugins-ci-package-manager.yml@v4.1.0
package/.taprc CHANGED
@@ -1 +1,3 @@
1
- check-coverage: false
1
+ disable-coverage: true
2
+ files:
3
+ - test/**/*.test.js
package/index.js CHANGED
@@ -204,6 +204,7 @@ function parse (uri, opts) {
204
204
  fragment: undefined
205
205
  }
206
206
  const gotEncoding = uri.indexOf('%') !== -1
207
+ let isIP = false
207
208
  if (options.reference === 'suffix') uri = (options.scheme ? options.scheme + ':' : '') + '//' + uri
208
209
 
209
210
  const matches = uri.match(URI_PARSE)
@@ -225,9 +226,12 @@ function parse (uri, opts) {
225
226
  if (parsed.host) {
226
227
  const ipv4result = normalizeIPv4(parsed.host)
227
228
  if (ipv4result.isIPV4 === false) {
228
- parsed.host = normalizeIPv6(ipv4result.host, { isIPV4: false }).host.toLowerCase()
229
+ const ipv6result = normalizeIPv6(ipv4result.host, { isIPV4: false })
230
+ parsed.host = ipv6result.host.toLowerCase()
231
+ isIP = ipv6result.isIPV6
229
232
  } else {
230
233
  parsed.host = ipv4result.host
234
+ isIP = true
231
235
  }
232
236
  }
233
237
  if (parsed.scheme === undefined && parsed.userinfo === undefined && parsed.host === undefined && parsed.port === undefined && !parsed.path && parsed.query === undefined) {
@@ -251,7 +255,7 @@ function parse (uri, opts) {
251
255
  // check if scheme can't handle IRIs
252
256
  if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport)) {
253
257
  // if host component is a domain name
254
- if (parsed.host && (options.domainHost || (schemeHandler && schemeHandler.domainHost)) && nonSimpleDomain(parsed.host)) {
258
+ if (parsed.host && (options.domainHost || (schemeHandler && schemeHandler.domainHost)) && isIP === false && nonSimpleDomain(parsed.host)) {
255
259
  // convert Unicode IDN -> ASCII IDN
256
260
  try {
257
261
  parsed.host = URL.domainToASCII(parsed.host.toLowerCase())
@@ -291,6 +295,7 @@ function parse (uri, opts) {
291
295
  }
292
296
 
293
297
  const fastUri = {
298
+ SCHEMES,
294
299
  normalize,
295
300
  resolve,
296
301
  resolveComponents,
package/lib/utils.js CHANGED
@@ -4,7 +4,7 @@ const { HEX } = require('./scopedChars')
4
4
 
5
5
  function normalizeIPv4 (host) {
6
6
  if (findToken(host, '.') < 3) { return { host, isIPV4: false } }
7
- const matches = host.match(/^(\b[01]?\d{1,2}|\b2[0-4]\d|\b25[0-5])(\.([01]?\d{1,2}|2[0-4]\d|25[0-5])){3}$/u) || []
7
+ const matches = host.match(/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/u) || []
8
8
  const [address] = matches
9
9
  if (address) {
10
10
  return { host: stripLeadingZeros(address, '.'), isIPV4: true }
@@ -13,14 +13,20 @@ function normalizeIPv4 (host) {
13
13
  }
14
14
  }
15
15
 
16
- function stringToHexStripped (input) {
16
+ /**
17
+ * @param {string[]} input
18
+ * @param {boolean} [keepZero=false]
19
+ * @returns {string|undefined}
20
+ */
21
+ function stringArrayToHexStripped (input, keepZero = false) {
17
22
  let acc = ''
18
23
  let strip = true
19
24
  for (const c of input) {
20
- if (c !== '0' && strip === true) strip = false
21
25
  if (HEX[c] === undefined) return undefined
26
+ if (c !== '0' && strip === true) strip = false
22
27
  if (!strip) acc += c
23
28
  }
29
+ if (keepZero && acc.length === 0) acc = '0'
24
30
  return acc
25
31
  }
26
32
 
@@ -36,7 +42,7 @@ function getIPV6 (input) {
36
42
  function consume () {
37
43
  if (buffer.length) {
38
44
  if (isZone === false) {
39
- const hex = stringToHexStripped(buffer.join(''))
45
+ const hex = stringArrayToHexStripped(buffer)
40
46
  if (hex !== undefined) {
41
47
  address.push(hex)
42
48
  } else {
@@ -83,7 +89,7 @@ function getIPV6 (input) {
83
89
  } else if (endIpv6) {
84
90
  address.push(buffer.join(''))
85
91
  } else {
86
- address.push(stringToHexStripped(buffer.join('')))
92
+ address.push(stringArrayToHexStripped(buffer))
87
93
  }
88
94
  }
89
95
  output.address = address.join('')
@@ -232,5 +238,5 @@ module.exports = {
232
238
  removeDotSegments,
233
239
  normalizeIPv4,
234
240
  normalizeIPv6,
235
- stringToHexStripped
241
+ stringArrayToHexStripped
236
242
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fast-uri",
3
3
  "description": "Dependency free RFC 3986 URI toolbox",
4
- "version": "2.4.0",
4
+ "version": "3.0.0",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",
7
7
  "types": "types/index.d.ts",
@@ -17,20 +17,21 @@
17
17
  "homepage": "https://github.com/fastify/fast-uri",
18
18
  "scripts": {
19
19
  "bench": "node benchmark.js",
20
+ "lint": "standard | snazzy",
20
21
  "lint:fix": "standard --fix",
21
- "test:lint": "standard | snazzy",
22
- "test:typescript": "tsd",
23
- "test:unit": "tap -J test/*.test.js",
24
- "test:unit:dev": "tap -J test/*.test.js --coverage-report=html",
25
- "test": "npm run test:lint && npm run test:unit && npm run test:typescript",
26
- "test:ci": "npm run test:lint && npm run test:unit -- --cov --coverage-report=lcovonly && npm run test:typescript"
22
+ "test": "npm run lint && npm run test:unit && npm run test:typescript",
23
+ "test:ci": "npm run lint && npm run test:unit -- --coverage-report=lcovonly && npm run test:typescript",
24
+ "test:unit": "tap",
25
+ "test:unit:dev": "npm run test:unit -- --coverage-report=html",
26
+ "test:typescript": "tsd"
27
27
  },
28
28
  "devDependencies": {
29
+ "@fastify/pre-commit": "^2.1.0",
29
30
  "benchmark": "^2.1.4",
30
31
  "coveralls": "^3.1.1",
31
32
  "snazzy": "^9.0.0",
32
- "standard": "^17.0.0",
33
- "tap": "^16.0.0",
33
+ "standard": "^17.1.0",
34
+ "tap": "^18.7.2",
34
35
  "tsd": "^0.31.0",
35
36
  "uri-js": "^4.4.1"
36
37
  }
@@ -11,7 +11,7 @@ test('compatibility Parse', (t) => {
11
11
  'https://fastify.org',
12
12
  '/definitions/Record%3Cstring%2CPerson%3E',
13
13
  '//10.10.10.10',
14
- '//10.10.000.10',
14
+ // '//10.10.000.10', <-- not a valid URI per URI spec: https://datatracker.ietf.org/doc/html/rfc5954#section-4.1
15
15
  '//[2001:db8::7%en0]',
16
16
  '//[2001:dbZ::1]:80',
17
17
  '//[2001:db8::1]:80',
@@ -174,12 +174,21 @@ test('URI parse', (t) => {
174
174
  t.equal(components.query, undefined, 'query')
175
175
  t.equal(components.fragment, undefined, 'fragment')
176
176
 
177
- // IPv4address with unformated 0
178
- components = URI.parse('//10.10.000.10')
177
+ // IPv4address with unformated 0 stay as-is
178
+ components = URI.parse('//10.10.000.10') // not valid as per https://datatracker.ietf.org/doc/html/rfc5954#section-4.1
179
179
  t.equal(components.error, undefined, 'IPv4address errors')
180
180
  t.equal(components.scheme, undefined, 'scheme')
181
181
  t.equal(components.userinfo, undefined, 'userinfo')
182
- t.equal(components.host, '10.10.0.10', 'host')
182
+ t.equal(components.host, '10.10.000.10', 'host')
183
+ t.equal(components.port, undefined, 'port')
184
+ t.equal(components.path, '', 'path')
185
+ t.equal(components.query, undefined, 'query')
186
+ t.equal(components.fragment, undefined, 'fragment')
187
+ components = URI.parse('//01.01.01.01') // not valid in URIs: https://datatracker.ietf.org/doc/html/rfc3986#section-7.4
188
+ t.equal(components.error, undefined, 'IPv4address errors')
189
+ t.equal(components.scheme, undefined, 'scheme')
190
+ t.equal(components.userinfo, undefined, 'userinfo')
191
+ t.equal(components.host, '01.01.01.01', 'host')
183
192
  t.equal(components.port, undefined, 'port')
184
193
  t.equal(components.path, '', 'path')
185
194
  t.equal(components.query, undefined, 'query')
@@ -0,0 +1,940 @@
1
+ 'use strict'
2
+
3
+ const {
4
+ ok,
5
+ same: deepEqual,
6
+ strictSame: strictEqual,
7
+ notSame: notStrictEqual,
8
+ test: tapTest
9
+ } = require('tap')
10
+
11
+ const test = function () {
12
+ if (typeof arguments[2] === 'function') {
13
+ tapTest(arguments[0], arguments[1], t => {
14
+ arguments[2](t)
15
+ t.end()
16
+ })
17
+ } else {
18
+ tapTest(arguments[0], t => {
19
+ arguments[1](t)
20
+ t.end()
21
+ })
22
+ }
23
+ }
24
+
25
+ const URI = require('../index')
26
+
27
+ /**
28
+ * URI.js
29
+ *
30
+ * @fileoverview An RFC 3986 compliant, scheme extendable URI parsing/normalizing/resolving/serializing library for JavaScript.
31
+ * @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
32
+ * @see http://github.com/garycourt/uri-js
33
+ */
34
+
35
+ /**
36
+ * Copyright 2011 Gary Court. All rights reserved.
37
+ *
38
+ * Redistribution and use in source and binary forms, with or without modification, are
39
+ * permitted provided that the following conditions are met:
40
+ *
41
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
42
+ * conditions and the following disclaimer.
43
+ *
44
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
45
+ * of conditions and the following disclaimer in the documentation and/or other materials
46
+ * provided with the distribution.
47
+ *
48
+ * THIS SOFTWARE IS PROVIDED BY GARY COURT ``AS IS'' AND ANY EXPRESS OR IMPLIED
49
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
50
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARY COURT OR
51
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
52
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
53
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
54
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
55
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
56
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57
+ *
58
+ * The views and conclusions contained in the software and documentation are those of the
59
+ * authors and should not be interpreted as representing official policies, either expressed
60
+ * or implied, of Gary Court.
61
+ */
62
+
63
+ test('Acquire URI', function () {
64
+ // URI = require("./uri").URI;
65
+ ok(URI)
66
+ })
67
+
68
+ test('URI Parsing', function () {
69
+ let components
70
+
71
+ // scheme
72
+ components = URI.parse('uri:')
73
+ strictEqual(components.error, undefined, 'scheme errors')
74
+ strictEqual(components.scheme, 'uri', 'scheme')
75
+ // strictEqual(components.authority, undefined, "authority");
76
+ strictEqual(components.userinfo, undefined, 'userinfo')
77
+ strictEqual(components.host, undefined, 'host')
78
+ strictEqual(components.port, undefined, 'port')
79
+ strictEqual(components.path, '', 'path')
80
+ strictEqual(components.query, undefined, 'query')
81
+ strictEqual(components.fragment, undefined, 'fragment')
82
+
83
+ // userinfo
84
+ components = URI.parse('//@')
85
+ strictEqual(components.error, undefined, 'userinfo errors')
86
+ strictEqual(components.scheme, undefined, 'scheme')
87
+ // strictEqual(components.authority, "@", "authority");
88
+ strictEqual(components.userinfo, '', 'userinfo')
89
+ strictEqual(components.host, '', 'host')
90
+ strictEqual(components.port, undefined, 'port')
91
+ strictEqual(components.path, '', 'path')
92
+ strictEqual(components.query, undefined, 'query')
93
+ strictEqual(components.fragment, undefined, 'fragment')
94
+
95
+ // host
96
+ components = URI.parse('//')
97
+ strictEqual(components.error, undefined, 'host errors')
98
+ strictEqual(components.scheme, undefined, 'scheme')
99
+ // strictEqual(components.authority, "", "authority");
100
+ strictEqual(components.userinfo, undefined, 'userinfo')
101
+ strictEqual(components.host, '', 'host')
102
+ strictEqual(components.port, undefined, 'port')
103
+ strictEqual(components.path, '', 'path')
104
+ strictEqual(components.query, undefined, 'query')
105
+ strictEqual(components.fragment, undefined, 'fragment')
106
+
107
+ // port
108
+ components = URI.parse('//:')
109
+ strictEqual(components.error, undefined, 'port errors')
110
+ strictEqual(components.scheme, undefined, 'scheme')
111
+ // strictEqual(components.authority, ":", "authority");
112
+ strictEqual(components.userinfo, undefined, 'userinfo')
113
+ strictEqual(components.host, '', 'host')
114
+ strictEqual(components.port, '', 'port')
115
+ strictEqual(components.path, '', 'path')
116
+ strictEqual(components.query, undefined, 'query')
117
+ strictEqual(components.fragment, undefined, 'fragment')
118
+
119
+ // path
120
+ components = URI.parse('')
121
+ strictEqual(components.error, undefined, 'path errors')
122
+ strictEqual(components.scheme, undefined, 'scheme')
123
+ // strictEqual(components.authority, undefined, "authority");
124
+ strictEqual(components.userinfo, undefined, 'userinfo')
125
+ strictEqual(components.host, undefined, 'host')
126
+ strictEqual(components.port, undefined, 'port')
127
+ strictEqual(components.path, '', 'path')
128
+ strictEqual(components.query, undefined, 'query')
129
+ strictEqual(components.fragment, undefined, 'fragment')
130
+
131
+ // query
132
+ components = URI.parse('?')
133
+ strictEqual(components.error, undefined, 'query errors')
134
+ strictEqual(components.scheme, undefined, 'scheme')
135
+ // strictEqual(components.authority, undefined, "authority");
136
+ strictEqual(components.userinfo, undefined, 'userinfo')
137
+ strictEqual(components.host, undefined, 'host')
138
+ strictEqual(components.port, undefined, 'port')
139
+ strictEqual(components.path, '', 'path')
140
+ strictEqual(components.query, '', 'query')
141
+ strictEqual(components.fragment, undefined, 'fragment')
142
+
143
+ // fragment
144
+ components = URI.parse('#')
145
+ strictEqual(components.error, undefined, 'fragment errors')
146
+ strictEqual(components.scheme, undefined, 'scheme')
147
+ // strictEqual(components.authority, undefined, "authority");
148
+ strictEqual(components.userinfo, undefined, 'userinfo')
149
+ strictEqual(components.host, undefined, 'host')
150
+ strictEqual(components.port, undefined, 'port')
151
+ strictEqual(components.path, '', 'path')
152
+ strictEqual(components.query, undefined, 'query')
153
+ strictEqual(components.fragment, '', 'fragment')
154
+
155
+ // fragment with character tabulation
156
+ components = URI.parse('#\t')
157
+ strictEqual(components.error, undefined, 'path errors')
158
+ strictEqual(components.scheme, undefined, 'scheme')
159
+ // strictEqual(components.authority, undefined, "authority");
160
+ strictEqual(components.userinfo, undefined, 'userinfo')
161
+ strictEqual(components.host, undefined, 'host')
162
+ strictEqual(components.port, undefined, 'port')
163
+ strictEqual(components.path, '', 'path')
164
+ strictEqual(components.query, undefined, 'query')
165
+ strictEqual(components.fragment, '%09', 'fragment')
166
+
167
+ // fragment with line feed
168
+ components = URI.parse('#\n')
169
+ strictEqual(components.error, undefined, 'path errors')
170
+ strictEqual(components.scheme, undefined, 'scheme')
171
+ // strictEqual(components.authority, undefined, "authority");
172
+ strictEqual(components.userinfo, undefined, 'userinfo')
173
+ strictEqual(components.host, undefined, 'host')
174
+ strictEqual(components.port, undefined, 'port')
175
+ strictEqual(components.path, '', 'path')
176
+ strictEqual(components.query, undefined, 'query')
177
+ strictEqual(components.fragment, '%0A', 'fragment')
178
+
179
+ // fragment with line tabulation
180
+ components = URI.parse('#\v')
181
+ strictEqual(components.error, undefined, 'path errors')
182
+ strictEqual(components.scheme, undefined, 'scheme')
183
+ // strictEqual(components.authority, undefined, "authority");
184
+ strictEqual(components.userinfo, undefined, 'userinfo')
185
+ strictEqual(components.host, undefined, 'host')
186
+ strictEqual(components.port, undefined, 'port')
187
+ strictEqual(components.path, '', 'path')
188
+ strictEqual(components.query, undefined, 'query')
189
+ strictEqual(components.fragment, '%0B', 'fragment')
190
+
191
+ // fragment with form feed
192
+ components = URI.parse('#\f')
193
+ strictEqual(components.error, undefined, 'path errors')
194
+ strictEqual(components.scheme, undefined, 'scheme')
195
+ // strictEqual(components.authority, undefined, "authority");
196
+ strictEqual(components.userinfo, undefined, 'userinfo')
197
+ strictEqual(components.host, undefined, 'host')
198
+ strictEqual(components.port, undefined, 'port')
199
+ strictEqual(components.path, '', 'path')
200
+ strictEqual(components.query, undefined, 'query')
201
+ strictEqual(components.fragment, '%0C', 'fragment')
202
+
203
+ // fragment with carriage return
204
+ components = URI.parse('#\r')
205
+ strictEqual(components.error, undefined, 'path errors')
206
+ strictEqual(components.scheme, undefined, 'scheme')
207
+ // strictEqual(components.authority, undefined, "authority");
208
+ strictEqual(components.userinfo, undefined, 'userinfo')
209
+ strictEqual(components.host, undefined, 'host')
210
+ strictEqual(components.port, undefined, 'port')
211
+ strictEqual(components.path, '', 'path')
212
+ strictEqual(components.query, undefined, 'query')
213
+ strictEqual(components.fragment, '%0D', 'fragment')
214
+
215
+ // all
216
+ components = URI.parse('uri://user:pass@example.com:123/one/two.three?q1=a1&q2=a2#body')
217
+ strictEqual(components.error, undefined, 'all errors')
218
+ strictEqual(components.scheme, 'uri', 'scheme')
219
+ // strictEqual(components.authority, "user:pass@example.com:123", "authority");
220
+ strictEqual(components.userinfo, 'user:pass', 'userinfo')
221
+ strictEqual(components.host, 'example.com', 'host')
222
+ strictEqual(components.port, 123, 'port')
223
+ strictEqual(components.path, '/one/two.three', 'path')
224
+ strictEqual(components.query, 'q1=a1&q2=a2', 'query')
225
+ strictEqual(components.fragment, 'body', 'fragment')
226
+
227
+ // IPv4address
228
+ components = URI.parse('//10.10.10.10')
229
+ strictEqual(components.error, undefined, 'IPv4address errors')
230
+ strictEqual(components.scheme, undefined, 'scheme')
231
+ strictEqual(components.userinfo, undefined, 'userinfo')
232
+ strictEqual(components.host, '10.10.10.10', 'host')
233
+ strictEqual(components.port, undefined, 'port')
234
+ strictEqual(components.path, '', 'path')
235
+ strictEqual(components.query, undefined, 'query')
236
+ strictEqual(components.fragment, undefined, 'fragment')
237
+
238
+ // IPv6address
239
+ components = URI.parse('//[2001:db8::7]')
240
+ strictEqual(components.error, undefined, 'IPv4address errors')
241
+ strictEqual(components.scheme, undefined, 'scheme')
242
+ strictEqual(components.userinfo, undefined, 'userinfo')
243
+ strictEqual(components.host, '2001:db8::7', 'host')
244
+ strictEqual(components.port, undefined, 'port')
245
+ strictEqual(components.path, '', 'path')
246
+ strictEqual(components.query, undefined, 'query')
247
+ strictEqual(components.fragment, undefined, 'fragment')
248
+
249
+ // mixed IPv4address & IPv6address
250
+ components = URI.parse('//[::ffff:129.144.52.38]')
251
+ strictEqual(components.error, undefined, 'IPv4address errors')
252
+ strictEqual(components.scheme, undefined, 'scheme')
253
+ strictEqual(components.userinfo, undefined, 'userinfo')
254
+ strictEqual(components.host, '::ffff:129.144.52.38', 'host')
255
+ strictEqual(components.port, undefined, 'port')
256
+ strictEqual(components.path, '', 'path')
257
+ strictEqual(components.query, undefined, 'query')
258
+ strictEqual(components.fragment, undefined, 'fragment')
259
+
260
+ // mixed IPv4address & reg-name, example from terion-name (https://github.com/garycourt/uri-js/issues/4)
261
+ components = URI.parse('uri://10.10.10.10.example.com/en/process')
262
+ strictEqual(components.error, undefined, 'mixed errors')
263
+ strictEqual(components.scheme, 'uri', 'scheme')
264
+ strictEqual(components.userinfo, undefined, 'userinfo')
265
+ strictEqual(components.host, '10.10.10.10.example.com', 'host')
266
+ strictEqual(components.port, undefined, 'port')
267
+ strictEqual(components.path, '/en/process', 'path')
268
+ strictEqual(components.query, undefined, 'query')
269
+ strictEqual(components.fragment, undefined, 'fragment')
270
+
271
+ // IPv6address, example from bkw (https://github.com/garycourt/uri-js/pull/16)
272
+ components = URI.parse('//[2606:2800:220:1:248:1893:25c8:1946]/test')
273
+ strictEqual(components.error, undefined, 'IPv6address errors')
274
+ strictEqual(components.scheme, undefined, 'scheme')
275
+ strictEqual(components.userinfo, undefined, 'userinfo')
276
+ strictEqual(components.host, '2606:2800:220:1:248:1893:25c8:1946', 'host')
277
+ strictEqual(components.port, undefined, 'port')
278
+ strictEqual(components.path, '/test', 'path')
279
+ strictEqual(components.query, undefined, 'query')
280
+ strictEqual(components.fragment, undefined, 'fragment')
281
+
282
+ // IPv6address, example from RFC 5952
283
+ components = URI.parse('//[2001:db8::1]:80')
284
+ strictEqual(components.error, undefined, 'IPv6address errors')
285
+ strictEqual(components.scheme, undefined, 'scheme')
286
+ strictEqual(components.userinfo, undefined, 'userinfo')
287
+ strictEqual(components.host, '2001:db8::1', 'host')
288
+ strictEqual(components.port, 80, 'port')
289
+ strictEqual(components.path, '', 'path')
290
+ strictEqual(components.query, undefined, 'query')
291
+ strictEqual(components.fragment, undefined, 'fragment')
292
+
293
+ // IPv6address with zone identifier, RFC 6874
294
+ components = URI.parse('//[fe80::a%25en1]')
295
+ strictEqual(components.error, undefined, 'IPv4address errors')
296
+ strictEqual(components.scheme, undefined, 'scheme')
297
+ strictEqual(components.userinfo, undefined, 'userinfo')
298
+ strictEqual(components.host, 'fe80::a%en1', 'host')
299
+ strictEqual(components.port, undefined, 'port')
300
+ strictEqual(components.path, '', 'path')
301
+ strictEqual(components.query, undefined, 'query')
302
+ strictEqual(components.fragment, undefined, 'fragment')
303
+
304
+ // IPv6address with an unescaped interface specifier, example from pekkanikander (https://github.com/garycourt/uri-js/pull/22)
305
+ components = URI.parse('//[2001:db8::7%en0]')
306
+ strictEqual(components.error, undefined, 'IPv6address interface errors')
307
+ strictEqual(components.scheme, undefined, 'scheme')
308
+ strictEqual(components.userinfo, undefined, 'userinfo')
309
+ strictEqual(components.host, '2001:db8::7%en0', 'host')
310
+ strictEqual(components.port, undefined, 'port')
311
+ strictEqual(components.path, '', 'path')
312
+ strictEqual(components.query, undefined, 'query')
313
+ strictEqual(components.fragment, undefined, 'fragment')
314
+ })
315
+
316
+ test('URI Serialization', function () {
317
+ let components = {
318
+ scheme: undefined,
319
+ userinfo: undefined,
320
+ host: undefined,
321
+ port: undefined,
322
+ path: undefined,
323
+ query: undefined,
324
+ fragment: undefined
325
+ }
326
+ strictEqual(URI.serialize(components), '', 'Undefined Components')
327
+
328
+ components = {
329
+ scheme: '',
330
+ userinfo: '',
331
+ host: '',
332
+ port: 0,
333
+ path: '',
334
+ query: '',
335
+ fragment: ''
336
+ }
337
+ strictEqual(URI.serialize(components), '//@:0?#', 'Empty Components')
338
+
339
+ components = {
340
+ scheme: 'uri',
341
+ userinfo: 'foo:bar',
342
+ host: 'example.com',
343
+ port: 1,
344
+ path: 'path',
345
+ query: 'query',
346
+ fragment: 'fragment'
347
+ }
348
+ strictEqual(URI.serialize(components), 'uri://foo:bar@example.com:1/path?query#fragment', 'All Components')
349
+
350
+ components = {
351
+ scheme: 'uri',
352
+ host: 'example.com',
353
+ port: '9000'
354
+ }
355
+ strictEqual(URI.serialize(components), 'uri://example.com:9000', 'String port')
356
+
357
+ strictEqual(URI.serialize({ path: '//path' }), '/%2Fpath', 'Double slash path')
358
+ strictEqual(URI.serialize({ path: 'foo:bar' }), 'foo%3Abar', 'Colon path')
359
+ strictEqual(URI.serialize({ path: '?query' }), '%3Fquery', 'Query path')
360
+
361
+ // mixed IPv4address & reg-name, example from terion-name (https://github.com/garycourt/uri-js/issues/4)
362
+ strictEqual(URI.serialize({ host: '10.10.10.10.example.com' }), '//10.10.10.10.example.com', 'Mixed IPv4address & reg-name')
363
+
364
+ // IPv6address
365
+ strictEqual(URI.serialize({ host: '2001:db8::7' }), '//[2001:db8::7]', 'IPv6 Host')
366
+ strictEqual(URI.serialize({ host: '::ffff:129.144.52.38' }), '//[::ffff:129.144.52.38]', 'IPv6 Mixed Host')
367
+ strictEqual(URI.serialize({ host: '2606:2800:220:1:248:1893:25c8:1946' }), '//[2606:2800:220:1:248:1893:25c8:1946]', 'IPv6 Full Host')
368
+
369
+ // IPv6address with zone identifier, RFC 6874
370
+ strictEqual(URI.serialize({ host: 'fe80::a%en1' }), '//[fe80::a%25en1]', 'IPv6 Zone Unescaped Host')
371
+ strictEqual(URI.serialize({ host: 'fe80::a%25en1' }), '//[fe80::a%25en1]', 'IPv6 Zone Escaped Host')
372
+ })
373
+
374
+ test('URI Resolving', { skip: true }, function () {
375
+ // normal examples from RFC 3986
376
+ const base = 'uri://a/b/c/d;p?q'
377
+ strictEqual(URI.resolve(base, 'g:h'), 'g:h', 'g:h')
378
+ strictEqual(URI.resolve(base, 'g:h'), 'g:h', 'g:h')
379
+ strictEqual(URI.resolve(base, 'g'), 'uri://a/b/c/g', 'g')
380
+ strictEqual(URI.resolve(base, './g'), 'uri://a/b/c/g', './g')
381
+ strictEqual(URI.resolve(base, 'g/'), 'uri://a/b/c/g/', 'g/')
382
+ strictEqual(URI.resolve(base, '/g'), 'uri://a/g', '/g')
383
+ strictEqual(URI.resolve(base, '//g'), 'uri://g', '//g')
384
+ strictEqual(URI.resolve(base, '?y'), 'uri://a/b/c/d;p?y', '?y')
385
+ strictEqual(URI.resolve(base, 'g?y'), 'uri://a/b/c/g?y', 'g?y')
386
+ strictEqual(URI.resolve(base, '#s'), 'uri://a/b/c/d;p?q#s', '#s')
387
+ strictEqual(URI.resolve(base, 'g#s'), 'uri://a/b/c/g#s', 'g#s')
388
+ strictEqual(URI.resolve(base, 'g?y#s'), 'uri://a/b/c/g?y#s', 'g?y#s')
389
+ strictEqual(URI.resolve(base, ';x'), 'uri://a/b/c/;x', ';x')
390
+ strictEqual(URI.resolve(base, 'g;x'), 'uri://a/b/c/g;x', 'g;x')
391
+ strictEqual(URI.resolve(base, 'g;x?y#s'), 'uri://a/b/c/g;x?y#s', 'g;x?y#s')
392
+ strictEqual(URI.resolve(base, ''), 'uri://a/b/c/d;p?q', '')
393
+ strictEqual(URI.resolve(base, '.'), 'uri://a/b/c/', '.')
394
+ strictEqual(URI.resolve(base, './'), 'uri://a/b/c/', './')
395
+ strictEqual(URI.resolve(base, '..'), 'uri://a/b/', '..')
396
+ strictEqual(URI.resolve(base, '../'), 'uri://a/b/', '../')
397
+ strictEqual(URI.resolve(base, '../g'), 'uri://a/b/g', '../g')
398
+ strictEqual(URI.resolve(base, '../..'), 'uri://a/', '../..')
399
+ strictEqual(URI.resolve(base, '../../'), 'uri://a/', '../../')
400
+ strictEqual(URI.resolve(base, '../../g'), 'uri://a/g', '../../g')
401
+
402
+ // abnormal examples from RFC 3986
403
+ strictEqual(URI.resolve(base, '../../../g'), 'uri://a/g', '../../../g')
404
+ strictEqual(URI.resolve(base, '../../../../g'), 'uri://a/g', '../../../../g')
405
+
406
+ strictEqual(URI.resolve(base, '/./g'), 'uri://a/g', '/./g')
407
+ strictEqual(URI.resolve(base, '/../g'), 'uri://a/g', '/../g')
408
+ strictEqual(URI.resolve(base, 'g.'), 'uri://a/b/c/g.', 'g.')
409
+ strictEqual(URI.resolve(base, '.g'), 'uri://a/b/c/.g', '.g')
410
+ strictEqual(URI.resolve(base, 'g..'), 'uri://a/b/c/g..', 'g..')
411
+ strictEqual(URI.resolve(base, '..g'), 'uri://a/b/c/..g', '..g')
412
+
413
+ strictEqual(URI.resolve(base, './../g'), 'uri://a/b/g', './../g')
414
+ strictEqual(URI.resolve(base, './g/.'), 'uri://a/b/c/g/', './g/.')
415
+ strictEqual(URI.resolve(base, 'g/./h'), 'uri://a/b/c/g/h', 'g/./h')
416
+ strictEqual(URI.resolve(base, 'g/../h'), 'uri://a/b/c/h', 'g/../h')
417
+ strictEqual(URI.resolve(base, 'g;x=1/./y'), 'uri://a/b/c/g;x=1/y', 'g;x=1/./y')
418
+ strictEqual(URI.resolve(base, 'g;x=1/../y'), 'uri://a/b/c/y', 'g;x=1/../y')
419
+
420
+ strictEqual(URI.resolve(base, 'g?y/./x'), 'uri://a/b/c/g?y/./x', 'g?y/./x')
421
+ strictEqual(URI.resolve(base, 'g?y/../x'), 'uri://a/b/c/g?y/../x', 'g?y/../x')
422
+ strictEqual(URI.resolve(base, 'g#s/./x'), 'uri://a/b/c/g#s/./x', 'g#s/./x')
423
+ strictEqual(URI.resolve(base, 'g#s/../x'), 'uri://a/b/c/g#s/../x', 'g#s/../x')
424
+
425
+ strictEqual(URI.resolve(base, 'uri:g'), 'uri:g', 'uri:g')
426
+ strictEqual(URI.resolve(base, 'uri:g', { tolerant: true }), 'uri://a/b/c/g', 'uri:g')
427
+
428
+ // examples by PAEz
429
+ strictEqual(URI.resolve('//www.g.com/', '/adf\ngf'), '//www.g.com/adf%0Agf', '/adf\\ngf')
430
+ strictEqual(URI.resolve('//www.g.com/error\n/bleh/bleh', '..'), '//www.g.com/error%0A/', '//www.g.com/error\\n/bleh/bleh')
431
+ })
432
+
433
+ test('URI Normalizing', { skip: true }, function () {
434
+ // test from RFC 3987
435
+ strictEqual(URI.normalize('uri://www.example.org/red%09ros\xE9#red'), 'uri://www.example.org/red%09ros%C3%A9#red')
436
+
437
+ // IPv4address
438
+ strictEqual(URI.normalize('//192.068.001.000'), '//192.68.1.0')
439
+
440
+ // IPv6address, example from RFC 3513
441
+ strictEqual(URI.normalize('http://[1080::8:800:200C:417A]/'), 'http://[1080::8:800:200c:417a]/')
442
+
443
+ // IPv6address, examples from RFC 5952
444
+ strictEqual(URI.normalize('//[2001:0db8::0001]/'), '//[2001:db8::1]/')
445
+ strictEqual(URI.normalize('//[2001:db8::1:0000:1]/'), '//[2001:db8::1:0:1]/')
446
+ strictEqual(URI.normalize('//[2001:db8:0:0:0:0:2:1]/'), '//[2001:db8::2:1]/')
447
+ strictEqual(URI.normalize('//[2001:db8:0:1:1:1:1:1]/'), '//[2001:db8:0:1:1:1:1:1]/')
448
+ strictEqual(URI.normalize('//[2001:0:0:1:0:0:0:1]/'), '//[2001:0:0:1::1]/')
449
+ strictEqual(URI.normalize('//[2001:db8:0:0:1:0:0:1]/'), '//[2001:db8::1:0:0:1]/')
450
+ strictEqual(URI.normalize('//[2001:DB8::1]/'), '//[2001:db8::1]/')
451
+ strictEqual(URI.normalize('//[0:0:0:0:0:ffff:192.0.2.1]/'), '//[::ffff:192.0.2.1]/')
452
+
453
+ // Mixed IPv4 and IPv6 address
454
+ strictEqual(URI.normalize('//[1:2:3:4:5:6:192.0.2.1]/'), '//[1:2:3:4:5:6:192.0.2.1]/')
455
+ strictEqual(URI.normalize('//[1:2:3:4:5:6:192.068.001.000]/'), '//[1:2:3:4:5:6:192.68.1.0]/')
456
+ })
457
+
458
+ test('URI Equals', function () {
459
+ // test from RFC 3986
460
+ strictEqual(URI.equal('example://a/b/c/%7Bfoo%7D', 'eXAMPLE://a/./b/../b/%63/%7bfoo%7d'), true)
461
+
462
+ // test from RFC 3987
463
+ strictEqual(URI.equal('http://example.org/~user', 'http://example.org/%7euser'), true)
464
+ })
465
+
466
+ test('Escape Component', { skip: true }, function () {
467
+ let chr
468
+ for (let d = 0; d <= 129; ++d) {
469
+ chr = String.fromCharCode(d)
470
+ if (!chr.match(/[$&+,;=]/)) {
471
+ strictEqual(URI.escapeComponent(chr), encodeURIComponent(chr))
472
+ } else {
473
+ strictEqual(URI.escapeComponent(chr), chr)
474
+ }
475
+ }
476
+ strictEqual(URI.escapeComponent('\u00c0'), encodeURIComponent('\u00c0'))
477
+ strictEqual(URI.escapeComponent('\u07ff'), encodeURIComponent('\u07ff'))
478
+ strictEqual(URI.escapeComponent('\u0800'), encodeURIComponent('\u0800'))
479
+ strictEqual(URI.escapeComponent('\u30a2'), encodeURIComponent('\u30a2'))
480
+ })
481
+
482
+ test('Unescape Component', { skip: true }, function () {
483
+ let chr
484
+ for (let d = 0; d <= 129; ++d) {
485
+ chr = String.fromCharCode(d)
486
+ strictEqual(URI.unescapeComponent(encodeURIComponent(chr)), chr)
487
+ }
488
+ strictEqual(URI.unescapeComponent(encodeURIComponent('\u00c0')), '\u00c0')
489
+ strictEqual(URI.unescapeComponent(encodeURIComponent('\u07ff')), '\u07ff')
490
+ strictEqual(URI.unescapeComponent(encodeURIComponent('\u0800')), '\u0800')
491
+ strictEqual(URI.unescapeComponent(encodeURIComponent('\u30a2')), '\u30a2')
492
+ })
493
+
494
+ //
495
+ // IRI
496
+ //
497
+
498
+ const IRI_OPTION = { iri: true, unicodeSupport: true }
499
+
500
+ test('IRI Parsing', { skip: true }, function () {
501
+ const components = URI.parse('uri://us\xA0er:pa\uD7FFss@example.com:123/o\uF900ne/t\uFDCFwo.t\uFDF0hree?q1=a1\uF8FF\uE000&q2=a2#bo\uFFEFdy', IRI_OPTION)
502
+ strictEqual(components.error, undefined, 'all errors')
503
+ strictEqual(components.scheme, 'uri', 'scheme')
504
+ // strictEqual(components.authority, "us\xA0er:pa\uD7FFss@example.com:123", "authority");
505
+ strictEqual(components.userinfo, 'us\xA0er:pa\uD7FFss', 'userinfo')
506
+ strictEqual(components.host, 'example.com', 'host')
507
+ strictEqual(components.port, 123, 'port')
508
+ strictEqual(components.path, '/o\uF900ne/t\uFDCFwo.t\uFDF0hree', 'path')
509
+ strictEqual(components.query, 'q1=a1\uF8FF\uE000&q2=a2', 'query')
510
+ strictEqual(components.fragment, 'bo\uFFEFdy', 'fragment')
511
+ })
512
+
513
+ test('IRI Serialization', { skip: true }, function () {
514
+ const components = {
515
+ scheme: 'uri',
516
+ userinfo: 'us\xA0er:pa\uD7FFss',
517
+ host: 'example.com',
518
+ port: 123,
519
+ path: '/o\uF900ne/t\uFDCFwo.t\uFDF0hree',
520
+ query: 'q1=a1\uF8FF\uE000&q2=a2',
521
+ fragment: 'bo\uFFEFdy\uE001'
522
+ }
523
+ strictEqual(URI.serialize(components, IRI_OPTION), 'uri://us\xA0er:pa\uD7FFss@example.com:123/o\uF900ne/t\uFDCFwo.t\uFDF0hree?q1=a1\uF8FF\uE000&q2=a2#bo\uFFEFdy%EE%80%81')
524
+ })
525
+
526
+ test('IRI Normalizing', { skip: true }, function () {
527
+ strictEqual(URI.normalize('uri://www.example.org/red%09ros\xE9#red', IRI_OPTION), 'uri://www.example.org/red%09ros\xE9#red')
528
+ })
529
+
530
+ test('IRI Equals', { skip: true }, function () {
531
+ // example from RFC 3987
532
+ strictEqual(URI.equal('example://a/b/c/%7Bfoo%7D/ros\xE9', 'eXAMPLE://a/./b/../b/%63/%7bfoo%7d/ros%C3%A9', IRI_OPTION), true)
533
+ })
534
+
535
+ test('Convert IRI to URI', { skip: true }, function () {
536
+ // example from RFC 3987
537
+ strictEqual(URI.serialize(URI.parse('uri://www.example.org/red%09ros\xE9#red', IRI_OPTION)), 'uri://www.example.org/red%09ros%C3%A9#red')
538
+
539
+ // Internationalized Domain Name conversion via punycode example from RFC 3987
540
+ strictEqual(URI.serialize(URI.parse('uri://r\xE9sum\xE9.example.org', { iri: true, domainHost: true }), { domainHost: true }), 'uri://xn--rsum-bpad.example.org')
541
+ })
542
+
543
+ test('Convert URI to IRI', { skip: true }, function () {
544
+ // examples from RFC 3987
545
+ strictEqual(URI.serialize(URI.parse('uri://www.example.org/D%C3%BCrst'), IRI_OPTION), 'uri://www.example.org/D\xFCrst')
546
+ strictEqual(URI.serialize(URI.parse('uri://www.example.org/D%FCrst'), IRI_OPTION), 'uri://www.example.org/D%FCrst')
547
+ strictEqual(URI.serialize(URI.parse('uri://xn--99zt52a.example.org/%e2%80%ae'), IRI_OPTION), 'uri://xn--99zt52a.example.org/%E2%80%AE') // or uri://\u7D0D\u8C46.example.org/%E2%80%AE
548
+
549
+ // Internationalized Domain Name conversion via punycode example from RFC 3987
550
+ strictEqual(URI.serialize(URI.parse('uri://xn--rsum-bpad.example.org', { domainHost: true }), { iri: true, domainHost: true }), 'uri://r\xE9sum\xE9.example.org')
551
+ })
552
+
553
+ //
554
+ // HTTP
555
+ //
556
+
557
+ if (URI.SCHEMES.http) {
558
+ // module("HTTP");
559
+
560
+ test('HTTP Equals', function () {
561
+ // test from RFC 2616
562
+ strictEqual(URI.equal('http://abc.com:80/~smith/home.html', 'http://abc.com/~smith/home.html'), true)
563
+ strictEqual(URI.equal('http://ABC.com/%7Esmith/home.html', 'http://abc.com/~smith/home.html'), true)
564
+ strictEqual(URI.equal('http://ABC.com:/%7esmith/home.html', 'http://abc.com/~smith/home.html'), true)
565
+ strictEqual(URI.equal('HTTP://ABC.COM', 'http://abc.com/'), true)
566
+ // test from RFC 3986
567
+ strictEqual(URI.equal('http://example.com:/', 'http://example.com:80/'), true)
568
+ })
569
+ }
570
+
571
+ if (URI.SCHEMES.https) {
572
+ // module("HTTPS");
573
+
574
+ test('HTTPS Equals', function () {
575
+ strictEqual(URI.equal('https://example.com', 'https://example.com:443/'), true)
576
+ strictEqual(URI.equal('https://example.com:/', 'https://example.com:443/'), true)
577
+ })
578
+ }
579
+
580
+ //
581
+ // URN
582
+ //
583
+
584
+ if (URI.SCHEMES.urn) {
585
+ // module("URN");
586
+
587
+ test('URN Parsing', function () {
588
+ // example from RFC 2141
589
+ const components = URI.parse('urn:foo:a123,456')
590
+ strictEqual(components.error, undefined, 'errors')
591
+ strictEqual(components.scheme, 'urn', 'scheme')
592
+ // strictEqual(components.authority, undefined, "authority");
593
+ strictEqual(components.userinfo, undefined, 'userinfo')
594
+ strictEqual(components.host, undefined, 'host')
595
+ strictEqual(components.port, undefined, 'port')
596
+ strictEqual(components.path, undefined, 'path')
597
+ strictEqual(components.query, undefined, 'query')
598
+ strictEqual(components.fragment, undefined, 'fragment')
599
+ strictEqual(components.nid, 'foo', 'nid')
600
+ strictEqual(components.nss, 'a123,456', 'nss')
601
+ })
602
+
603
+ test('URN Serialization', function () {
604
+ // example from RFC 2141
605
+ const components = {
606
+ scheme: 'urn',
607
+ nid: 'foo',
608
+ nss: 'a123,456'
609
+ }
610
+ strictEqual(URI.serialize(components), 'urn:foo:a123,456')
611
+ })
612
+
613
+ test('URN Equals', { skip: true }, function () {
614
+ // test from RFC 2141
615
+ strictEqual(URI.equal('urn:foo:a123,456', 'urn:foo:a123,456'), true)
616
+ strictEqual(URI.equal('urn:foo:a123,456', 'URN:foo:a123,456'), true)
617
+ strictEqual(URI.equal('urn:foo:a123,456', 'urn:FOO:a123,456'), true)
618
+ strictEqual(URI.equal('urn:foo:a123,456', 'urn:foo:A123,456'), false)
619
+ strictEqual(URI.equal('urn:foo:a123%2C456', 'URN:FOO:a123%2c456'), true)
620
+ })
621
+
622
+ test('URN Resolving', function () {
623
+ // example from epoberezkin
624
+ strictEqual(URI.resolve('', 'urn:some:ip:prop'), 'urn:some:ip:prop')
625
+ strictEqual(URI.resolve('#', 'urn:some:ip:prop'), 'urn:some:ip:prop')
626
+ strictEqual(URI.resolve('urn:some:ip:prop', 'urn:some:ip:prop'), 'urn:some:ip:prop')
627
+ strictEqual(URI.resolve('urn:some:other:prop', 'urn:some:ip:prop'), 'urn:some:ip:prop')
628
+ })
629
+
630
+ //
631
+ // URN UUID
632
+ //
633
+
634
+ test('UUID Parsing', function () {
635
+ // example from RFC 4122
636
+ let components = URI.parse('urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6')
637
+ strictEqual(components.error, undefined, 'errors')
638
+ strictEqual(components.scheme, 'urn', 'scheme')
639
+ // strictEqual(components.authority, undefined, "authority");
640
+ strictEqual(components.userinfo, undefined, 'userinfo')
641
+ strictEqual(components.host, undefined, 'host')
642
+ strictEqual(components.port, undefined, 'port')
643
+ strictEqual(components.path, undefined, 'path')
644
+ strictEqual(components.query, undefined, 'query')
645
+ strictEqual(components.fragment, undefined, 'fragment')
646
+ strictEqual(components.nid, 'uuid', 'nid')
647
+ strictEqual(components.nss, undefined, 'nss')
648
+ strictEqual(components.uuid, 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6', 'uuid')
649
+
650
+ components = URI.parse('urn:uuid:notauuid-7dec-11d0-a765-00a0c91e6bf6')
651
+ notStrictEqual(components.error, undefined, 'errors')
652
+ })
653
+
654
+ test('UUID Serialization', function () {
655
+ // example from RFC 4122
656
+ let components = {
657
+ scheme: 'urn',
658
+ nid: 'uuid',
659
+ uuid: 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6'
660
+ }
661
+ strictEqual(URI.serialize(components), 'urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6')
662
+
663
+ components = {
664
+ scheme: 'urn',
665
+ nid: 'uuid',
666
+ uuid: 'notauuid-7dec-11d0-a765-00a0c91e6bf6'
667
+ }
668
+ strictEqual(URI.serialize(components), 'urn:uuid:notauuid-7dec-11d0-a765-00a0c91e6bf6')
669
+ })
670
+
671
+ test('UUID Equals', function () {
672
+ strictEqual(URI.equal('URN:UUID:F81D4FAE-7DEC-11D0-A765-00A0C91E6BF6', 'urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6'), true)
673
+ })
674
+
675
+ test('URN NID Override', function () {
676
+ let components = URI.parse('urn:foo:f81d4fae-7dec-11d0-a765-00a0c91e6bf6', { nid: 'uuid' })
677
+ strictEqual(components.error, undefined, 'errors')
678
+ strictEqual(components.scheme, 'urn', 'scheme')
679
+ strictEqual(components.path, undefined, 'path')
680
+ strictEqual(components.nid, 'foo', 'nid')
681
+ strictEqual(components.nss, undefined, 'nss')
682
+ strictEqual(components.uuid, 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6', 'uuid')
683
+
684
+ components = {
685
+ scheme: 'urn',
686
+ nid: 'foo',
687
+ uuid: 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6'
688
+ }
689
+ strictEqual(URI.serialize(components, { nid: 'uuid' }), 'urn:foo:f81d4fae-7dec-11d0-a765-00a0c91e6bf6')
690
+ })
691
+ }
692
+
693
+ //
694
+ // Mailto
695
+ //
696
+
697
+ if (URI.SCHEMES.mailto) {
698
+ // module("Mailto");
699
+
700
+ test('Mailto Parse', function () {
701
+ let components
702
+
703
+ // tests from RFC 6068
704
+
705
+ components = URI.parse('mailto:chris@example.com')
706
+ strictEqual(components.error, undefined, 'error')
707
+ strictEqual(components.scheme, 'mailto', 'scheme')
708
+ strictEqual(components.userinfo, undefined, 'userinfo')
709
+ strictEqual(components.host, undefined, 'host')
710
+ strictEqual(components.port, undefined, 'port')
711
+ strictEqual(components.path, undefined, 'path')
712
+ strictEqual(components.query, undefined, 'query')
713
+ strictEqual(components.fragment, undefined, 'fragment')
714
+ deepEqual(components.to, ['chris@example.com'], 'to')
715
+ strictEqual(components.subject, undefined, 'subject')
716
+ strictEqual(components.body, undefined, 'body')
717
+ strictEqual(components.headers, undefined, 'headers')
718
+
719
+ components = URI.parse('mailto:infobot@example.com?subject=current-issue')
720
+ deepEqual(components.to, ['infobot@example.com'], 'to')
721
+ strictEqual(components.subject, 'current-issue', 'subject')
722
+
723
+ components = URI.parse('mailto:infobot@example.com?body=send%20current-issue')
724
+ deepEqual(components.to, ['infobot@example.com'], 'to')
725
+ strictEqual(components.body, 'send current-issue', 'body')
726
+
727
+ components = URI.parse('mailto:infobot@example.com?body=send%20current-issue%0D%0Asend%20index')
728
+ deepEqual(components.to, ['infobot@example.com'], 'to')
729
+ strictEqual(components.body, 'send current-issue\x0D\x0Asend index', 'body')
730
+
731
+ components = URI.parse('mailto:list@example.org?In-Reply-To=%3C3469A91.D10AF4C@example.com%3E')
732
+ deepEqual(components.to, ['list@example.org'], 'to')
733
+ deepEqual(components.headers, { 'In-Reply-To': '<3469A91.D10AF4C@example.com>' }, 'headers')
734
+
735
+ components = URI.parse('mailto:majordomo@example.com?body=subscribe%20bamboo-l')
736
+ deepEqual(components.to, ['majordomo@example.com'], 'to')
737
+ strictEqual(components.body, 'subscribe bamboo-l', 'body')
738
+
739
+ components = URI.parse('mailto:joe@example.com?cc=bob@example.com&body=hello')
740
+ deepEqual(components.to, ['joe@example.com'], 'to')
741
+ strictEqual(components.body, 'hello', 'body')
742
+ deepEqual(components.headers, { cc: 'bob@example.com' }, 'headers')
743
+
744
+ components = URI.parse('mailto:joe@example.com?cc=bob@example.com?body=hello')
745
+ if (URI.VALIDATE_SUPPORT) ok(components.error, 'invalid header fields')
746
+
747
+ components = URI.parse('mailto:gorby%25kremvax@example.com')
748
+ deepEqual(components.to, ['gorby%kremvax@example.com'], 'to gorby%kremvax@example.com')
749
+
750
+ components = URI.parse('mailto:unlikely%3Faddress@example.com?blat=foop')
751
+ deepEqual(components.to, ['unlikely?address@example.com'], 'to unlikely?address@example.com')
752
+ deepEqual(components.headers, { blat: 'foop' }, 'headers')
753
+
754
+ components = URI.parse('mailto:Mike%26family@example.org')
755
+ deepEqual(components.to, ['Mike&family@example.org'], 'to Mike&family@example.org')
756
+
757
+ components = URI.parse('mailto:%22not%40me%22@example.org')
758
+ deepEqual(components.to, ['"not@me"@example.org'], 'to ' + '"not@me"@example.org')
759
+
760
+ components = URI.parse('mailto:%22oh%5C%5Cno%22@example.org')
761
+ deepEqual(components.to, ['"oh\\\\no"@example.org'], 'to ' + '"oh\\\\no"@example.org')
762
+
763
+ components = URI.parse("mailto:%22%5C%5C%5C%22it's%5C%20ugly%5C%5C%5C%22%22@example.org")
764
+ deepEqual(components.to, ['"\\\\\\"it\'s\\ ugly\\\\\\""@example.org'], 'to ' + '"\\\\\\"it\'s\\ ugly\\\\\\""@example.org')
765
+
766
+ components = URI.parse('mailto:user@example.org?subject=caf%C3%A9')
767
+ deepEqual(components.to, ['user@example.org'], 'to')
768
+ strictEqual(components.subject, 'caf\xE9', 'subject')
769
+
770
+ components = URI.parse('mailto:user@example.org?subject=%3D%3Futf-8%3FQ%3Fcaf%3DC3%3DA9%3F%3D')
771
+ deepEqual(components.to, ['user@example.org'], 'to')
772
+ strictEqual(components.subject, '=?utf-8?Q?caf=C3=A9?=', 'subject') // TODO: Verify this
773
+
774
+ components = URI.parse('mailto:user@example.org?subject=%3D%3Fiso-8859-1%3FQ%3Fcaf%3DE9%3F%3D')
775
+ deepEqual(components.to, ['user@example.org'], 'to')
776
+ strictEqual(components.subject, '=?iso-8859-1?Q?caf=E9?=', 'subject') // TODO: Verify this
777
+
778
+ components = URI.parse('mailto:user@example.org?subject=caf%C3%A9&body=caf%C3%A9')
779
+ deepEqual(components.to, ['user@example.org'], 'to')
780
+ strictEqual(components.subject, 'caf\xE9', 'subject')
781
+ strictEqual(components.body, 'caf\xE9', 'body')
782
+
783
+ if (URI.IRI_SUPPORT) {
784
+ components = URI.parse('mailto:user@%E7%B4%8D%E8%B1%86.example.org?subject=Test&body=NATTO')
785
+ deepEqual(components.to, ['user@xn--99zt52a.example.org'], 'to')
786
+ strictEqual(components.subject, 'Test', 'subject')
787
+ strictEqual(components.body, 'NATTO', 'body')
788
+ }
789
+ })
790
+
791
+ test('Mailto Serialize', function () {
792
+ // tests from RFC 6068
793
+ strictEqual(URI.serialize({ scheme: 'mailto', to: ['chris@example.com'] }), 'mailto:chris@example.com')
794
+ strictEqual(URI.serialize({ scheme: 'mailto', to: ['infobot@example.com'], body: 'current-issue' }), 'mailto:infobot@example.com?body=current-issue')
795
+ strictEqual(URI.serialize({ scheme: 'mailto', to: ['infobot@example.com'], body: 'send current-issue' }), 'mailto:infobot@example.com?body=send%20current-issue')
796
+ strictEqual(URI.serialize({ scheme: 'mailto', to: ['infobot@example.com'], body: 'send current-issue\x0D\x0Asend index' }), 'mailto:infobot@example.com?body=send%20current-issue%0D%0Asend%20index')
797
+ strictEqual(URI.serialize({ scheme: 'mailto', to: ['list@example.org'], headers: { 'In-Reply-To': '<3469A91.D10AF4C@example.com>' } }), 'mailto:list@example.org?In-Reply-To=%3C3469A91.D10AF4C@example.com%3E')
798
+ strictEqual(URI.serialize({ scheme: 'mailto', to: ['majordomo@example.com'], body: 'subscribe bamboo-l' }), 'mailto:majordomo@example.com?body=subscribe%20bamboo-l')
799
+ strictEqual(URI.serialize({ scheme: 'mailto', to: ['joe@example.com'], headers: { cc: 'bob@example.com', body: 'hello' } }), 'mailto:joe@example.com?cc=bob@example.com&body=hello')
800
+ strictEqual(URI.serialize({ scheme: 'mailto', to: ['gorby%25kremvax@example.com'] }), 'mailto:gorby%25kremvax@example.com')
801
+ strictEqual(URI.serialize({ scheme: 'mailto', to: ['unlikely%3Faddress@example.com'], headers: { blat: 'foop' } }), 'mailto:unlikely%3Faddress@example.com?blat=foop')
802
+ strictEqual(URI.serialize({ scheme: 'mailto', to: ['Mike&family@example.org'] }), 'mailto:Mike%26family@example.org')
803
+ strictEqual(URI.serialize({ scheme: 'mailto', to: ['"not@me"@example.org'] }), 'mailto:%22not%40me%22@example.org')
804
+ strictEqual(URI.serialize({ scheme: 'mailto', to: ['"oh\\\\no"@example.org'] }), 'mailto:%22oh%5C%5Cno%22@example.org')
805
+ strictEqual(URI.serialize({ scheme: 'mailto', to: ['"\\\\\\"it\'s\\ ugly\\\\\\""@example.org'] }), "mailto:%22%5C%5C%5C%22it's%5C%20ugly%5C%5C%5C%22%22@example.org")
806
+ strictEqual(URI.serialize({ scheme: 'mailto', to: ['user@example.org'], subject: 'caf\xE9' }), 'mailto:user@example.org?subject=caf%C3%A9')
807
+ strictEqual(URI.serialize({ scheme: 'mailto', to: ['user@example.org'], subject: '=?utf-8?Q?caf=C3=A9?=' }), 'mailto:user@example.org?subject=%3D%3Futf-8%3FQ%3Fcaf%3DC3%3DA9%3F%3D')
808
+ strictEqual(URI.serialize({ scheme: 'mailto', to: ['user@example.org'], subject: '=?iso-8859-1?Q?caf=E9?=' }), 'mailto:user@example.org?subject=%3D%3Fiso-8859-1%3FQ%3Fcaf%3DE9%3F%3D')
809
+ strictEqual(URI.serialize({ scheme: 'mailto', to: ['user@example.org'], subject: 'caf\xE9', body: 'caf\xE9' }), 'mailto:user@example.org?subject=caf%C3%A9&body=caf%C3%A9')
810
+ if (URI.IRI_SUPPORT) {
811
+ strictEqual(URI.serialize({ scheme: 'mailto', to: ['us\xE9r@\u7d0d\u8c46.example.org'], subject: 'Test', body: 'NATTO' }), 'mailto:us%C3%A9r@xn--99zt52a.example.org?subject=Test&body=NATTO')
812
+ }
813
+ })
814
+
815
+ test('Mailto Equals', function () {
816
+ // tests from RFC 6068
817
+ strictEqual(URI.equal('mailto:addr1@an.example,addr2@an.example', 'mailto:?to=addr1@an.example,addr2@an.example'), true)
818
+ strictEqual(URI.equal('mailto:?to=addr1@an.example,addr2@an.example', 'mailto:addr1@an.example?to=addr2@an.example'), true)
819
+ })
820
+ }
821
+
822
+ if (URI.SCHEMES.ws) {
823
+ // module("WS");
824
+
825
+ test('WS Parse', function () {
826
+ let components
827
+
828
+ // example from RFC 6455, Sec 4.1
829
+ components = URI.parse('ws://example.com/chat')
830
+ strictEqual(components.error, undefined, 'error')
831
+ strictEqual(components.scheme, 'ws', 'scheme')
832
+ strictEqual(components.userinfo, undefined, 'userinfo')
833
+ strictEqual(components.host, 'example.com', 'host')
834
+ strictEqual(components.port, undefined, 'port')
835
+ strictEqual(components.path, undefined, 'path')
836
+ strictEqual(components.query, undefined, 'query')
837
+ strictEqual(components.fragment, undefined, 'fragment')
838
+ strictEqual(components.resourceName, '/chat', 'resourceName')
839
+ strictEqual(components.secure, false, 'secure')
840
+
841
+ components = URI.parse('ws://example.com/foo?bar=baz')
842
+ strictEqual(components.error, undefined, 'error')
843
+ strictEqual(components.scheme, 'ws', 'scheme')
844
+ strictEqual(components.userinfo, undefined, 'userinfo')
845
+ strictEqual(components.host, 'example.com', 'host')
846
+ strictEqual(components.port, undefined, 'port')
847
+ strictEqual(components.path, undefined, 'path')
848
+ strictEqual(components.query, undefined, 'query')
849
+ strictEqual(components.fragment, undefined, 'fragment')
850
+ strictEqual(components.resourceName, '/foo?bar=baz', 'resourceName')
851
+ strictEqual(components.secure, false, 'secure')
852
+
853
+ components = URI.parse('ws://example.com/?bar=baz')
854
+ strictEqual(components.resourceName, '/?bar=baz', 'resourceName')
855
+ })
856
+
857
+ test('WS Serialize', function () {
858
+ strictEqual(URI.serialize({ scheme: 'ws' }), 'ws:')
859
+ strictEqual(URI.serialize({ scheme: 'ws', host: 'example.com' }), 'ws://example.com')
860
+ strictEqual(URI.serialize({ scheme: 'ws', resourceName: '/' }), 'ws:')
861
+ strictEqual(URI.serialize({ scheme: 'ws', resourceName: '/foo' }), 'ws:/foo')
862
+ strictEqual(URI.serialize({ scheme: 'ws', resourceName: '/foo?bar' }), 'ws:/foo?bar')
863
+ strictEqual(URI.serialize({ scheme: 'ws', secure: false }), 'ws:')
864
+ strictEqual(URI.serialize({ scheme: 'ws', secure: true }), 'wss:')
865
+ strictEqual(URI.serialize({ scheme: 'ws', host: 'example.com', resourceName: '/foo' }), 'ws://example.com/foo')
866
+ strictEqual(URI.serialize({ scheme: 'ws', host: 'example.com', resourceName: '/foo?bar' }), 'ws://example.com/foo?bar')
867
+ strictEqual(URI.serialize({ scheme: 'ws', host: 'example.com', secure: false }), 'ws://example.com')
868
+ strictEqual(URI.serialize({ scheme: 'ws', host: 'example.com', secure: true }), 'wss://example.com')
869
+ strictEqual(URI.serialize({ scheme: 'ws', host: 'example.com', resourceName: '/foo?bar', secure: false }), 'ws://example.com/foo?bar')
870
+ strictEqual(URI.serialize({ scheme: 'ws', host: 'example.com', resourceName: '/foo?bar', secure: true }), 'wss://example.com/foo?bar')
871
+ })
872
+
873
+ test('WS Equal', function () {
874
+ strictEqual(URI.equal('WS://ABC.COM:80/chat#one', 'ws://abc.com/chat'), true)
875
+ })
876
+
877
+ test('WS Normalize', function () {
878
+ strictEqual(URI.normalize('ws://example.com:80/foo#hash'), 'ws://example.com/foo')
879
+ })
880
+ }
881
+
882
+ if (URI.SCHEMES.wss) {
883
+ // module("WSS");
884
+
885
+ test('WSS Parse', function () {
886
+ let components
887
+
888
+ // example from RFC 6455, Sec 4.1
889
+ components = URI.parse('wss://example.com/chat')
890
+ strictEqual(components.error, undefined, 'error')
891
+ strictEqual(components.scheme, 'wss', 'scheme')
892
+ strictEqual(components.userinfo, undefined, 'userinfo')
893
+ strictEqual(components.host, 'example.com', 'host')
894
+ strictEqual(components.port, undefined, 'port')
895
+ strictEqual(components.path, undefined, 'path')
896
+ strictEqual(components.query, undefined, 'query')
897
+ strictEqual(components.fragment, undefined, 'fragment')
898
+ strictEqual(components.resourceName, '/chat', 'resourceName')
899
+ strictEqual(components.secure, true, 'secure')
900
+
901
+ components = URI.parse('wss://example.com/foo?bar=baz')
902
+ strictEqual(components.error, undefined, 'error')
903
+ strictEqual(components.scheme, 'wss', 'scheme')
904
+ strictEqual(components.userinfo, undefined, 'userinfo')
905
+ strictEqual(components.host, 'example.com', 'host')
906
+ strictEqual(components.port, undefined, 'port')
907
+ strictEqual(components.path, undefined, 'path')
908
+ strictEqual(components.query, undefined, 'query')
909
+ strictEqual(components.fragment, undefined, 'fragment')
910
+ strictEqual(components.resourceName, '/foo?bar=baz', 'resourceName')
911
+ strictEqual(components.secure, true, 'secure')
912
+
913
+ components = URI.parse('wss://example.com/?bar=baz')
914
+ strictEqual(components.resourceName, '/?bar=baz', 'resourceName')
915
+ })
916
+
917
+ test('WSS Serialize', function () {
918
+ strictEqual(URI.serialize({ scheme: 'wss' }), 'wss:')
919
+ strictEqual(URI.serialize({ scheme: 'wss', host: 'example.com' }), 'wss://example.com')
920
+ strictEqual(URI.serialize({ scheme: 'wss', resourceName: '/' }), 'wss:')
921
+ strictEqual(URI.serialize({ scheme: 'wss', resourceName: '/foo' }), 'wss:/foo')
922
+ strictEqual(URI.serialize({ scheme: 'wss', resourceName: '/foo?bar' }), 'wss:/foo?bar')
923
+ strictEqual(URI.serialize({ scheme: 'wss', secure: false }), 'ws:')
924
+ strictEqual(URI.serialize({ scheme: 'wss', secure: true }), 'wss:')
925
+ strictEqual(URI.serialize({ scheme: 'wss', host: 'example.com', resourceName: '/foo' }), 'wss://example.com/foo')
926
+ strictEqual(URI.serialize({ scheme: 'wss', host: 'example.com', resourceName: '/foo?bar' }), 'wss://example.com/foo?bar')
927
+ strictEqual(URI.serialize({ scheme: 'wss', host: 'example.com', secure: false }), 'ws://example.com')
928
+ strictEqual(URI.serialize({ scheme: 'wss', host: 'example.com', secure: true }), 'wss://example.com')
929
+ strictEqual(URI.serialize({ scheme: 'wss', host: 'example.com', resourceName: '/foo?bar', secure: false }), 'ws://example.com/foo?bar')
930
+ strictEqual(URI.serialize({ scheme: 'wss', host: 'example.com', resourceName: '/foo?bar', secure: true }), 'wss://example.com/foo?bar')
931
+ })
932
+
933
+ test('WSS Equal', function () {
934
+ strictEqual(URI.equal('WSS://ABC.COM:443/chat#one', 'wss://abc.com/chat'), true)
935
+ })
936
+
937
+ test('WSS Normalize', function () {
938
+ strictEqual(URI.normalize('wss://example.com:443/foo#hash'), 'wss://example.com/foo')
939
+ })
940
+ }
@@ -0,0 +1,24 @@
1
+ 'use strict'
2
+
3
+ const tap = require('tap')
4
+ const test = tap.test
5
+ const {
6
+ stringArrayToHexStripped
7
+ } = require('../lib/utils')
8
+
9
+ test('stringArrayToHexStripped', (t) => {
10
+ const testCases = [
11
+ [[['0', '0', '0', '0']], ''],
12
+ [[['0', '0', '0', '0'], false], ''],
13
+ [[['0', '0', '0', '0'], true], '0'],
14
+ [[['0', '1', '0', '0'], false], '100'],
15
+ [[['1', '0', '0', '0'], false], '1000'],
16
+ [[['1', '0', '0', '0'], true], '1000']
17
+ ]
18
+
19
+ t.plan(testCases.length)
20
+
21
+ testCases.forEach(([input, expected]) => {
22
+ t.strictSame(stringArrayToHexStripped(input[0], input[1]), expected)
23
+ })
24
+ })