Bug #17293
closedURI.parse fails to parse correctly URN or other special characters in path/url
Description
URI.parse looks to fail parsing endpoints that have special characters. For example:
url = 'http://foobar.com/#/applications/'
path = 'my_application'
URI.join(url, path).to_s
The result renders http://foobar.com/my_application
.
Or in the case of executing an API marked by URNs so the ID field in my GET request is something like
key = 'urn:api:baz:1'
url = 'http://foobar.com/api'
URI.join(url, key).to_s
The result renders urn:api:baz:1
.
Updated by jeremyevans0 (Jeremy Evans) over 3 years ago
- Status changed from Open to Rejected
greg.howdeshell (Greg Howdeshell) wrote:
URI.parse looks to fail parsing endpoints that have special characters. For example:
url = 'http://foobar.com/#/applications/' path = 'my_application' URI.join(url, path).to_s
The result renders
http://foobar.com/my_application
.
This is expected. The #/applications/
is an anchor/fragment, not part of the path (path is /
). For my_application
, that is interpreted as the path, so it overwrites the path of the url
. You get the same result for URI.join('http://foobar.com/', 'my_application').to_s
.
Or in the case of executing an API marked by URNs so the ID field in my GET request is something like
key = 'urn:api:baz:1' url = 'http://foobar.com/api' URI.join(url, key).to_s
The result renders
urn:api:baz:1
.
The issue here is that 'urn:api:baz:1'
is interpreted as a URI with scheme urn
and opaque part api:baz:1
, which overrides the entire url.
The URI.join
documents the behavior: String(s) to work with, will be converted to RFC3986 URIs before merging.
.
You probably don't want to use URI.join
in either example. You may want something like the following, but I'm not even sure of what URIs you are trying to generate:
url = 'http://foobar.com/#/applications/'
path = 'my_application'
uri = URI.parse(url)
uri.fragment += path
uri.to_s
# => "http://foobar.com/#/applications/my_application"
key = 'urn:api:baz:1'
url = 'http://foobar.com/api'
uri = URI.parse(url)
uri.query = "ID=#{key}"
uri.to_s
# => "http://foobar.com/api?ID=urn:api:baz:1"