How do I safely join relative url segments? How do I safely join relative url segments? ruby ruby

How do I safely join relative url segments?


URI's api is not neccearily great.

URI::join will work only if the first one starts out as an absolute uri with protocol, and the later ones are relative in the right ways... except I try to do that and can't even get that to work.

This at least doesn't error, but why is it skipping the middle component?

 URI::join('http://somewhere.com/resource', './edit', '12?option=test') 

I think maybe URI just kind of sucks. It lacks significant api on instances, such as an instance #join or method to evaluate relative to a base uri, that you'd expect. It's just kinda crappy.

I think you're going to have to write it yourself. Or just use File.join and other File path methods, after testing all the edge cases you can think of to make sure it does what you want/expect.

edit 9 Dec 2016 I figured out the addressable gem does it very nicely.

base = Addressable::URI.parse("http://example.com")base + "foo.html"# => #<Addressable::URI:0x3ff9964aabe4 URI:http://example.com/foo.html>base = Addressable::URI.parse("http://example.com/path/to/file.html")base + "relative_file.xml"# => #<Addressable::URI:0x3ff99648bc80 URI:http://example.com/path/to/relative_file.xml>base = Addressable::URI.parse("https://example.com/path")base + "//newhost/somewhere.jpg"# => #<Addressable::URI:0x3ff9960c9ebc URI:https://newhost/somewhere.jpg>base = Addressable::URI.parse("http://example.com/path/subpath/file.html")base + "../up-one-level.html"=> #<Addressable::URI:0x3fe13ec5e928 URI:http://example.com/path/up-one-level.html>


Have uri as URI::Generic or subclass of thereof

uri.path += '/123' 

Enjoy!

06/25/2016 UPDATE for skeptical folk

require 'uri'uri = URI('http://ioffe.net/boris')uri.path += '/123'p uri

Outputs

 <URI::HTTP:0x2341a58 URL:http://ioffe.net/boris/123>

Run me


The problem is that resource/ is relative to the current directory, but /edit refers to the top level directory due to the leading slash. It's impossible to join the two directories without already knowing for certain that edit contains resource.

If you're looking for purely string operations, simply remove the leading or trailing slashes from all parts, then join them with / as the glue.