Ruby OpenURI FTP не работает, когда в имени пользователя есть пробелы

Я использую Ruby 1.9.3 и выполняю следующую команду:

open("ftp://user name:[email protected]/1234/1234.txt.gz")

который возвращает:

URI::InvalidURIError: неверный URI (это не URI?)

Кодирование имени пользователя (замена пробелов на %20) также не работает:

Net::FTPPermError: 530 Неверный идентификатор пользователя/пароль

URI отлично работает во всех протестированных браузерах и FTP-клиентах, но не при использовании OpenURI. Кроме того, использование Net::FTP (обернутое OpenURI) также отлично работает:

require 'net/ftp'
ftp = Net::FTP.new
ftp.connect("datafeeds.domain.com", 21)
ftp.login("user name", "password")
ftp.getbinaryfile("/1234/1234.txt.gz")

Есть идеи, почему метод OpenURI не работает, а метод Net::FTP работает? Спасибо.


person modulaaron    schedule 27.06.2013    source источник


Ответы (3)


По определению в спецификации, в именах пользователей URL разрешены только следующие символы:

user                   alphanum2 [ user ]
[...]
alphanum2              alpha | digit | - | _ | . | +  

Браузеры печально известны тем, что игнорируют спецификации, поэтому заявления о том, что они поддерживают их, не являются хорошим доказательством. Они не должны соответствовать спецификации.

Если cURL их поддерживает, используйте гем Curb и посмотрите, позволит ли он вам их использовать.

person the Tin Man    schedule 27.06.2013
comment
Спасибо. Не уверен, видели ли вы, но я отредактировал пост около 5 минут назад, добавив тот факт, что Net::FTP работает нормально. Мы используем его на данный момент, но в идеале хотелось бы использовать только OpenURI (поскольку Het::HTTP также будет использоваться в приложении). - person modulaaron; 28.06.2013
comment
Опечатка выше: Het::HTTP =›› Net::HTTP - person modulaaron; 28.06.2013

Согласно этому ответу StackOverflow, вы должны иметь возможность просто избегайте специальных символов в имени пользователя и пароле. Вы можете сделать что-то вроде:

login = URI.escape('user name') + ':' + URI.escape('password')
open("ftp://#{login}@datafeeds.domain.com/1234/1234.txt.gz")
person Jacob Brown    schedule 27.06.2013
comment
Я тоже так думал, но в этом случае преобразование пробелов в %20 приводит к ошибке аутентификации FTP. - person modulaaron; 28.06.2013
comment
Что произойдет, если вы попытаетесь экранировать в стиле CGI.escape, например, open("ftp://user+name:[email protected]/1234/1234.txt.gz")? - person Jacob Brown; 28.06.2013
comment
Та же проблема при использовании имени пользователя + имени вместо имени пользователя. - person modulaaron; 29.06.2013

open-uri кажется сломанным в этом вопросе. У меня была аналогичная проблема с паролем, который содержал символ #.

В итоге я обошел set_password, который не допускает # char в пароле, установив переменную экземпляра @password URI напрямую.

uri = URI.parse(...)
if uri.password
  uri.instance_variable_set "@password", "password_with_#_char"
end
open(uri) # now this works fine

Это хакерский, но делает работу.

person Michał Szajbe    schedule 21.04.2017