shankardevy
shankardevy

Reputation: 4370

URI encoding not working

On a rails app, I need to parse uris

a = 'some file name.txt'
URI(URI.encode(a)) # works

b = 'some filename with :colon in it.txt'
URI(URI.encode(b)) # fails URI::InvalidURIError: bad URI(is not URI?): 

How can I safely pass a file name to URI that contains special characters? Why doesn't encode work on colon?

Upvotes: 5

Views: 4819

Answers (5)

Stefan
Stefan

Reputation: 114138

URI.escape (or encode) takes an optional second parameter. It's a Regexp matching all symbols that should be escaped. To escape all non-word characters you could use:

URI.encode('some filename with :colon in it.txt', /\W/)
#=> "some%20filename%20with%20%3Acolon%20in%20it%2Etxt"

There are two predefined regular expressions for encode:

URI::PATTERN::UNRESERVED  #=> "\\-_.!~*'()a-zA-Z\\d"
URI::PATTERN::RESERVED    #=> ";/?:@&=+$,\\[\\]"

Upvotes: 12

7stud
7stud

Reputation: 48599

require 'uri'

url = "file1:abc.txt"
p URI.encode_www_form_component url

--output:--
"file1%3Aabc.txt"


p URI(URI.encode_www_form_component url)

--output:--
#<URI::Generic:0x000001008abf28 URL:file1%3Aabc.txt>


p URI(URI.encode url, ":")

--output:--
#<URI::Generic:0x000001008abcd0 URL:file1%3Aabc.txt>

Why doesn't encode work on colon?

Because encode/escape is broken.

Upvotes: 2

Arup Rakshit
Arup Rakshit

Reputation: 118261

Use Addressable::URI::encode

require "addressable/uri"

a = 'some file name.txt'
Addressable::URI.encode(Addressable::URI.encode(a))
# => "some%2520file%2520name.txt"

b = 'some filename with :colon in it.txt'
Addressable::URI.encode(Addressable::URI.encode(b)) 
# => "some%2520filename%2520with%2520:colon%2520in%2520it.txt"

Upvotes: 1

Saravanan
Saravanan

Reputation: 1440

If you want to escape special character from the given string. It is best to use

esc_uri=URI.escape("String with special character")

The result string is URI escaped string and safe to pass it to URI. Refer URI::Escape for how to use URI escape. Hope this helps.

Upvotes: -1

MurifoX
MurifoX

Reputation: 15089

The problem seems to be the empty space preceding the colon, 'lol :lol.txt' don't work, but 'lol:lol.txt' works.
Maybe you could replace the spaces for something else.

Upvotes: 0

Related Questions