3

我正在尝试一个简单的重定向到该模式的 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 类解析的情况下进行重定向?

(西纳特拉 1.4.3,红宝石 1.9.3p194)

4

2 回答 2

2

我认为问题不是响应,而是后续请求。该错误由 URI 库引发,因为 uri看起来确实无效。Sinatra 不解析 uri并且WEBrick 仅使用 URI解析请求

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

来自RFC - 统一资源标识符 (URI):通用语法

例如,“文件”URI 方案被定义为没有权限、空主机和“本地主机”都表示最终用户的机器,而“http”方案认为缺少权限或空主机无效。

这是一个 HTTP 服务器,所以你必须帮助它 - 看这个问答


作为我在此处和下面的评论中提到的示例,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

于 2013-11-10T19:14:23.087 回答
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
于 2013-11-12T14:27:19.593 回答