malformed-percent.test.js 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. 'use strict'
  2. const test = require('tape')
  3. const fastURI = require('..')
  4. const MALFORMED_PERCENT_ERROR = 'URI contains malformed percent-encoding.'
  5. const malformedComponents = [
  6. ['path', 'x://example.test/a%'],
  7. ['path with one trailing hex digit', 'x://example.test/a%2'],
  8. ['path with non-hex digits', 'x://example.test/a%GG'],
  9. ['host', 'x://exa%mple.test/path'],
  10. ['userinfo', 'x://us%er@example.test/path'],
  11. ['query', 'x://example.test/path?q=%G0'],
  12. ['fragment', 'x://example.test/path#frag%1']
  13. ]
  14. test('parse reports malformed percent syntax in generic URI components', (t) => {
  15. for (const [component, uri] of malformedComponents) {
  16. t.equal(fastURI.parse(uri).error, MALFORMED_PERCENT_ERROR, component)
  17. }
  18. t.end()
  19. })
  20. test('normalize preserves malformed percent input unchanged', (t) => {
  21. for (const [component, uri] of malformedComponents) {
  22. t.equal(fastURI.normalize(uri), uri, component)
  23. }
  24. t.end()
  25. })
  26. test('equal does not equate malformed input with repaired valid input', (t) => {
  27. const cases = [
  28. ['x://example.test/a%', 'x://example.test/a%25'],
  29. ['x://exa%mple.test/path', 'x://exa%25mple.test/path'],
  30. ['x://us%er@example.test/path', 'x://us%25er@example.test/path'],
  31. ['x://example.test/path?q=%', 'x://example.test/path?q=%25'],
  32. ['x://example.test/path#%', 'x://example.test/path#%25']
  33. ]
  34. for (const [malformed, repaired] of cases) {
  35. t.equal(fastURI.equal(malformed, repaired, {}), false, malformed)
  36. }
  37. t.end()
  38. })
  39. test('resolve rejects malformed percent syntax in either input', (t) => {
  40. t.throws(
  41. () => fastURI.resolve('x://example.test/base%', 'child'),
  42. /URI contains malformed percent-encoding\./,
  43. 'malformed base'
  44. )
  45. t.throws(
  46. () => fastURI.resolve('x://example.test/base', 'child%'),
  47. /URI contains malformed percent-encoding\./,
  48. 'malformed relative reference'
  49. )
  50. t.end()
  51. })
  52. test('valid percent octets remain valid without UTF-8 validation', (t) => {
  53. const uri = '/%ff?q=%80#%fe'
  54. const parsed = fastURI.parse(uri)
  55. t.equal(parsed.error, undefined, 'non-UTF-8 octets are valid percent syntax')
  56. t.equal(parsed.path, '/%FF', 'path octet is preserved and hex is uppercased')
  57. t.equal(parsed.query, 'q=%80', 'query octet is preserved')
  58. t.equal(parsed.fragment, '%FE', 'fragment octet is preserved and hex is uppercased')
  59. t.equal(fastURI.normalize(uri), '/%FF?q=%80#%FE', 'normalization preserves the octets')
  60. const allGenericComponents = fastURI.parse('x://u%2f@exa%2fmple.test/%2f?q=%2f#%2f')
  61. t.equal(allGenericComponents.error, undefined, 'valid escapes are accepted in every generic component')
  62. const ipv6Zone = fastURI.parse('//[2001:db8::7%en0]')
  63. t.equal(ipv6Zone.error, undefined, 'historically accepted raw IPv6 zone separator is unchanged')
  64. t.end()
  65. })