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) about 5 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_sThe 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_sThe 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"