fastify / fast-uri

Dependency free RFC 3986 URI toolbox
Other
86 stars 7 forks source link

Relative paths don't survive serialize/parse #51

Closed epoberezkin closed 2 months ago

epoberezkin commented 2 years ago

Prerequisites

Fastify version

N/A

Plugin version

No response

Node.js version

16.0

Operating system

macOS

Operating system version (i.e. 20.04, 11.3, 10)

Mac

Description

Not sure it's a bug - is it intended? uri-js, annoyingly, does the same...

Steps to Reproduce

const uri = require('fast-uri')
let parsed = uri.parse('../one/two.three?q1=a1&q2=a2#body')
console.log(parsed)
console.log(uri.serialize(parsed))

// Output: // { // scheme : "uri", // userinfo : "user:pass", // host : "example.com", // port : 123, // path : "../one/two.three", // query : "q1=a1&q2=a2", // fragment : "body" // } // // "one/two.three?q1=a1&q2=a2#body"

https://runkit.com/esp/6319bd9f5b03ac0008add460

Expected Behavior

No response

zekth commented 2 years ago
const uri = require('fast-uri')
const urijs = require('uri-js')
let parsed = uri.parse('../one/two.three?q1=a1&q2=a2#body')
console.log(parsed)
console.log(uri.serialize(parsed))

parsed = urijs.parse('../one/two.three?q1=a1&q2=a2#body')
console.log(parsed)
console.log(urijs.serialize(parsed))
{
  scheme: undefined,       
  userinfo: undefined,     
  host: undefined,
  port: undefined,
  path: '../one/two.three',
  query: 'q1=a1&q2=a2',    
  fragment: 'body',        
  reference: 'relative'    
}
one/two.three?q1=a1&q2=a2#body
{
  scheme: undefined,
  userinfo: undefined,
  host: undefined,
  port: undefined,
  path: '../one/two.three',
  query: 'q1=a1&q2=a2',
  fragment: 'body',
  reference: 'relative'
}
one/two.three?q1=a1&q2=a2#body

It's same as old behaviour, but indeed it looks like a bug to me

Eomm commented 2 years ago

Doesn't it relate to this issue https://github.com/garycourt/uri-js/issues/31?

However, unlike in a file system, these dot-segments are only interpreted within the URI path hierarchy and are removed as part of the resolution process (Section 5.2).

https://www.ietf.org/rfc/rfc3986.txt

zekth commented 1 year ago

@epoberezkin just tried testing this and in fact with the absolutePath option it works. See:

'use strict'

const tap = require('tap')
const test = tap.test
const uri = require('../')

test('keep relative', (t) => {
    const inputs = [
        '../one/../two.three?q1=a1&q2=a2#body',
        '../one/two.three?q1=a1&q2=a2#body',
        '../../one/two.three?q1=a1&q2=a2#body',
    ]
    inputs.forEach((input) => {
        let parsed = uri.parse(input)
        t.same(uri.serialize(parsed, { absolutePath: true }), input, 'relative paths should be keeped')
    })
    t.end()
})

Does that fit your needs?