OpenURI 无法遵循具有 %20 的 URL

OpenURI fails to follow URLs that have %20

我在使用 Ruby 的 OpenURI 跟随重定向功能时遇到一些问题。

当转到其中包含 %20 的 URL 并使用 30x 重定向时,Ruby 的 OpenURI 失败。

代码

require 'open-uri'

base = "http://software-engineering-handbook.com/Handbook"

puts "===> PASS: URI Open +"
result = open "#{base}/Video+Series"
p result.status

puts "===> PASS: Curl +"
puts `curl -LIsS "#{base}/Video+Series" | grep HTTP`

puts "===> PASS: Curl %20"
puts `curl -LIsS "#{base}/Video%20Series" | grep HTTP`

puts "===> FAIL: URI Open %20"
begin
  result = open "#{base}/Video%20Series"
  p result.status
rescue => e
  puts "#{e.class} #{e.message}"
end

输出

===> PASS: URI Open +
["200", "OK"]
===> PASS: Curl +
HTTP/1.1 200 OK
===> PASS: Curl %20
HTTP/1.1 303 See Other
HTTP/1.1 200 OK
===> FAIL: URI Open %20
OpenURI::HTTPError 302 Found (Invalid Location URI)

我不确定这里发生了什么。尝试过 HTTParty(虽然我知道它只是一个包装器),希望看到不同的行为,但也失败了。

服务器正在响应一个指向无效 URI 的重定向。 curl 松懈,但 Ruby 严格。

如果我们打印出 e.cause,我们将获得更多信息。

#<URI::InvalidURIError: bad URI(is not URI?): "http://software-engineering-handbook.com/Handbook/Video Series/">

并且还通过查看 curl -I 'http://software-engineering-handbook.com/Handbook/Video%20Series' 中的 headers...

HTTP/1.1 303 See Other
Server: Cowboy
Date: Sat, 28 Dec 2019 21:41:28 GMT
Connection: keep-alive
Content-Type: text/html;charset=utf-8
Location: http://software-engineering-handbook.com/Handbook/Video Series/

事实上,服务器正在返回无效的 URI。 URI path 中不允许有空格。 Ruby 的 URI class 不会解析它。

> URI("http://software-engineering-handbook.com/Handbook/Video Series/")
URI::InvalidURIError: bad URI(is not URI?): "http://software-engineering-handbook.com/Handbook/Video Series/"
from /Users/schwern/.rvm/rubies/ruby-2.6.5/lib/ruby/2.6.0/uri/rfc3986_parser.rb:67:in `split'