How do I parse an encoded URI in Ruby?
I'm trying to parse a URI that has brackets - [ and ] - in it. I have tried to parse this directly with URI.parse but the brackets cause this to fail. I therefore tried to encode the URI with CGI::escape which takes care of the brackets but when I try to parse this encoded URI with URI.parse it doesn't seem to recognise it as a URI and puts the entire URI into the path object.
To demonstrate in an irb session;
irb(main):001:0> require 'uri'
=> true
irb(main):002:0> require 'cgi'
=> true
irb(main):003:0> name = "http://www.website.com/dir1/dir[2]/file.txt"
=> "http://www.website.com/dir1/dir[2]/file.txt"
irb(main):004:0> encoded_name = CGI::escape(name)
=> "http%3A%2F%2Fwww.website.com%2Fdir1%2Fdir%5B2%5D%2Ffile.txt"
irb(main):005:0> parsed_name = URI.parse(encoded_name)
=> #<URI::Generic:0x00000001e8f520 URL:http%3A%2F%2Fwww.website.com%2Fdir1%2Fdir%5B2%5D%2Ffile.txt>
irb(main):006:0> parsed_name.scheme
=> nil
irb(main):007:0> parsed_name.host
=> nil
irb(main):008:0> parsed_name.path
=> "http%3A%2F%2Fwww.website.com%2Fdir1%2Fdir%5B2%5D%2Ffile.txt"
irb(main):009:0> URI.split(encoded_name)
=> [nil, nil, nil, nil, nil, "http%3A%2F%2Fwww.website.com%2Fdir1%2Fdir%5B2%5D%2Ffile.txt", nil, nil, nil]
Anyway, my work around at the moment is the following ugly, but effective, hack
encoded_name = name.gsub(/\[/,"%5B").gsub(/\]/,"%5D")
Parsing this with URI.parse produces the desired result but won't cope if other strange characters find their way into my URIs. So my question is,开发者_StackOverflow is there a solid way of doing this that won't fall down?
The problem lies in trying to apply CGI::escape
to the whole URI. When you do that, you lose the front part of the URI that holds the scheme and the URI parser gets lost after that. You may want to try something based on mtyaka's answer:
irb(main):015:0> encoded_name = URI.encode(name, '[]')
=> "http://www.website.com/dir1/dir%5B2%5D/file.txt"
irb(main):016:0> parsed_name = URI.parse(encoded_name)
=> #<URI::HTTP:0xb76ff358 URL:http://www.website.com/dir1/dir%5B2%5D/file.txt>
irb(main):017:0> parsed_name.scheme
=> "http"
irb(main):018:0> parsed_name.host
=> "www.website.com"
irb(main):019:0> parsed_name.path
=> "/dir1/dir%5B2%5D/file.txt"
To get the original path, just URI.decode
whatever you get from parsed_name.path
.
You could use URI.encode
:
encoded_name = URI.encode(name, '[]')
精彩评论