Sinatra重定向到没有路径的URI

时间:2013-11-08 11:36:32

标签: ruby redirect sinatra

我正在尝试一个简单的重定向到该模式的iOS的OTA安装链接:

itms-services://?action=download-manifest&url=https://builds.net/abc.plist

无论尝试过的重定向方法Sinatra(webrick?)如何总是抱怨URI无效:ERROR URI::InvalidURIError: bad URI(absolute but no path):

我已经尝试过以下调用:

# Simple redirect
redirect 'itms-services://?action=download-manifest&url=https://builds.net/abc.plist'

# Raw headers redirect
status 302
headers 'Location' => 'itms-services://?action=download-manifest&url=https://builds.net/abc.plist'

# Halt redirect
halt 302, { 'Location' => 'itms-services://?action=download-manifest&url=https://builds.net/abc.plist' }, ''

始终导致相同的错误。

是否有可能在不触发URI类解析的情况下进行重定向?

(Sinatra 1.4.3,Ruby 1.9.3p194)

2 个答案:

答案 0 :(得分:2)

我不认为这是问题的反应,而是后续请求。 URI库引发错误,因为uri 看起来无效。 Sinatra doesn't parse the uriWEBrick only parses the requests using URI

您需要提供一个网络服务器可以使用的uri,一个没有主机名的uri,该方案不太可能被解析为有效或可用。

来自the RFC - Uniform Resource Identifier (URI): Generic Syntax

  

例如,"文件" URI   方案被定义为没有权限,空主机和   "本地主机"所有这些都意味着最终用户的机器,而" http"   scheme认为缺少权限或空主机无效。

它是一个HTTP服务器,因此您必须提供帮助 - 请参阅此Q&A


作为我在此处以及下面的评论中提到的一个例子,Sinatra通过重定向发送标头,网络服务器不应该在IRB会话中解析响应中的URI :

require 'sinatra/base'
# => false
class BadUri < Sinatra::Base
  get "/" do
      redirect 'itms-services://?action=download-manifest&url=https://builds.net/abc.plist'
    end
  end
# => [Az, [], [], #<Proc:0x000001009c50a8@/Users/iainuser/RubyProjects/Test/SO19858178/vendor/ruby/1.9.1/gems/sinatra-1.4.4/lib/sinatra/base.rb:1593>]
BadUri.run!
[2013-11-11 14:18:42] INFO  WEBrick 1.3.1
[2013-11-11 14:18:42] INFO  ruby 1.9.3 (2013-02-06) [x86_64-darwin10.8.0]
== Sinatra/1.4.4 has taken the stage on 4567 for development with backup from WEBrick
[2013-11-11 14:18:42] INFO  WEBrick::HTTPServer#start: pid=36540 port=4567

然后得到回复:

curl -D headers http://localhost:4567/

并在它转储的headers文件中:

HTTP/1.1 302 Found
Content-Type: text/html;charset=utf-8
Location: itms-services://?action=download-manifest&url=https://builds.net/abc.plist
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Length: 0

没有抛出任何错误。但这与彪马有关。我尝试使用Thin ...它也有效。有了Webrick,它会抛出一个错误,所以不要使用Webrick

答案 1 :(得分:2)

我终于提出了一个可以在Webrick上运行的解决方法,但是这段代码根本禁用了URI路径检查:

# Add empty pattern for URI hostname parsing to allow itms-services://? URIs
module URI
  def self.parse(uri)
    URI::Parser.new(:HOSTNAME => "(?:)|(?:#{::URI::REGEXP::PATTERN::HOSTNAME})").parse(uri)
  end
end