| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- 'use strict'
- const test = require('tape')
- const fastURI = require('..')
- const PATH_RESERVED = "!$&'()*+,;=:@/"
- function percentEncode (character, lowerCase) {
- const hex = character.charCodeAt(0).toString(16).padStart(2, '0')
- return '%' + (lowerCase ? hex : hex.toUpperCase())
- }
- test('normalize preserves literal and escaped reserved path characters', (t) => {
- t.equal(
- fastURI.normalize('http://example.com/a;b'),
- 'http://example.com/a;b',
- 'literal semicolon remains literal'
- )
- t.equal(
- fastURI.normalize('http://example.com/a%3ab'),
- 'http://example.com/a%3Ab',
- 'escaped colon remains escaped and its hex is uppercased'
- )
- for (const character of PATH_RESERVED) {
- const literal = `http://example.com/a${character}b`
- const escaped = `http://example.com/a${percentEncode(character, true)}b`
- const normalizedEscape = `http://example.com/a${percentEncode(character, false)}b`
- t.equal(fastURI.normalize(literal), literal, `preserves literal ${character}`)
- t.equal(fastURI.normalize(escaped), normalizedEscape, `preserves escaped ${character}`)
- }
- t.equal(
- fastURI.normalize('http://example.com/a/./café'),
- 'http://example.com/a/caf%C3%A9',
- 'removes real dot segments and UTF-8 encodes raw non-ASCII'
- )
- t.equal(
- fastURI.normalize('http://example.com/a/%2e%2e/b'),
- 'http://example.com/a/%2E%2E/b',
- 'preserves escaped dots as path data'
- )
- t.equal(
- fastURI.normalize('http://example.com/Kſ'),
- 'http://example.com/%E2%84%AA%C5%BF',
- 'UTF-8 encodes Unicode characters that case-fold to ASCII'
- )
- t.end()
- })
- test('serialize uses the RFC 3986 path character set without opening escapes', (t) => {
- const rawPath = `/a${PATH_RESERVED}b`
- t.equal(
- fastURI.serialize({ scheme: 'http', host: 'example.com', path: rawPath }),
- `http://example.com${rawPath}`,
- 'keeps all legal raw path characters'
- )
- const escapedPath = Array.from(PATH_RESERVED, (character) => percentEncode(character, true)).join('')
- const normalizedEscapedPath = Array.from(PATH_RESERVED, (character) => percentEncode(character, false)).join('')
- t.equal(
- fastURI.serialize({ scheme: 'http', host: 'example.com', path: '/' + escapedPath }),
- 'http://example.com/' + normalizedEscapedPath,
- 'uppercases valid escapes without decoding reserved characters'
- )
- t.equal(
- fastURI.serialize({ scheme: 'http', host: 'example.com', path: '/a?b#c[d]' }),
- 'http://example.com/a%3Fb%23c%5Bd%5D',
- 'encodes characters that would leave the path component'
- )
- t.equal(
- fastURI.serialize({ path: 'a:b/c:d' }),
- 'a%3Ab/c:d',
- 'only escapes a colon where path-noscheme requires it'
- )
- t.equal(
- fastURI.serialize({ path: './a:b/c:d' }),
- 'a%3Ab/c:d',
- 'escapes a first-segment colon exposed by dot-segment removal'
- )
- t.equal(
- fastURI.normalize('./a:b'),
- 'a%3Ab',
- 'normalization keeps a relative path from becoming a scheme'
- )
- t.equal(
- fastURI.serialize({ path: '/Kſ' }),
- '/%E2%84%AA%C5%BF',
- 'UTF-8 encodes Unicode characters that case-fold to ASCII'
- )
- t.end()
- })
- test('equal distinguishes escaped reserved path data from literal syntax', (t) => {
- for (const character of PATH_RESERVED) {
- const literal = `http://example.com/a${character}b`
- const escaped = `http://example.com/a${percentEncode(character, false)}b`
- t.equal(fastURI.equal(literal, escaped, {}), false, `distinguishes literal and escaped ${character}`)
- }
- t.equal(
- fastURI.equal('./a:b', 'a:b', {}),
- false,
- 'does not equate a relative path with an absolute URI after removing dot segments'
- )
- t.end()
- })
|