3

类似于“获取 HTTP 重定向页面的状态代码”,但使用 NET::HTTP 而不是遏制,我正在向将重定向的页面发出 GET 请求:

response = Net::HTTP.get_response(URI.parse("http://www.wikipedia.org/wiki/URL_redirection"))
puts response.code #{
puts response['location']

=> 301 
en.wikipedia.org/wiki/URL_redirection

问题是我想知道重定向页面的状态码。在这种情况下,它是 200,但在我的应用程序中,我想检查它是 200 还是其他东西。我看到的解决方案是只调用get_response(response['location']),但这在我的应用程序中不起作用,因为重定向的设计方式使得重定向只能被遵循一次。由于第一个 GET 消耗了那个重定向,所以我不能再关注它了。

有什么方法可以获取 GET 的最后一个状态码吗?


编辑:进一步澄清情况:

我发送 GET 到的应用程序有一个单点登录身份验证机制,如果我想访问“myapp/mypage”,我必须先发送一个帖子:

postResponse = Net::HTTP.post_form(URI.parse("http://myapp.com/trusted"), {"username" => @username})

然后发出 GET 请求:

'http://myapp.com/trusted/#{postResponse.body}/mypage

*这postResponse.body是一张可以兑换一次的“票”。

该 GET 验证票证是否有效,然后重定向到:

myapp.com/mypage

所以无论这张票是否有效,我都会得到一个 301。

我想查看最后进入 myapp.com/mypage 的状态码。

如果我手动尝试跟随重定向,无论是 HEAD 请求还是 GET,原始重定向将已经消耗了票证,因此即使原始重定向是 200,我也会收到票证已过期的错误。

4

2 回答 2

1

Net::HTTP 文档中的示例代码展示了如何处理重定向。你试过了吗?它应该可以很容易地进入重定向机制并在以后获取状态。

这是他们的例子:

跟随重定向

每个 Net::HTTPResponse 对象都属于其响应代码的一个类。

例如,所有 2XX 响应都是 Net::HTTPSuccess 子类的实例,3XX 响应是 Net::HTTPRedirection 子类的实例,而 200 响应是 Net::HTTPOK 类的实例。有关响应类的详细信息,请参阅下面的“HTTP 响应类”部分。

使用 case 语句,您可以正确处理各种类型的响应:

def fetch(uri_str, limit = 10)
  # You should choose a better exception.
  raise ArgumentError, 'too many HTTP redirects' if limit == 0

  response = Net::HTTP.get_response(URI(uri_str))

  case response
  when Net::HTTPSuccess then
    response
  when Net::HTTPRedirection then
    location = response['location']
    warn "redirected to #{location}"
    fetch(location, limit - 1)
  else
    response.value
  end
end

print fetch('http://www.ruby-lang.org')

像这样的小改动应该会有所帮助:

require 'net/http'

RESPONSES = []
def fetch(uri_str, limit = 10)
  # You should choose a better exception.
  raise ArgumentError, 'too many HTTP redirects' if limit == 0

  response = Net::HTTP.get_response(URI(uri_str))

  RESPONSES << response

  case response
  when Net::HTTPSuccess then
    response
  when Net::HTTPRedirection then
    location = response['location']
    warn "redirected to #{location}"
    fetch(location, limit - 1)
  else
    response.value
  end
end

print fetch('http://jigsaw.w3.org/HTTP/300/302.html')
puts RESPONSES.join("\n") # =>

当我运行它时,我看到了这个:

redirected to http://jigsaw.w3.org/HTTP/300/Overview.html
#<Net::HTTPOK:0x007f9e82a1e050>#<Net::HTTPFound:0x007f9e82a2daa0>
#<Net::HTTPOK:0x007f9e82a1e050>
于 2013-11-01T23:29:51.553 回答
0

如果仅在HTTP HEAD不“消耗”您的 URL 的情况下发出请求就足够了(这将是 HEAD 请求的通常期望),您可以这样做:

2.0.0-p195 :143 > result = Net::HTTP.start('www.google.com') { |http| http.head '/' }
 => #<Net::HTTPFound 302 Found readbody=true> 

所以在你的例子中你会这样做:

 ...
 result = Net::HTTP.start(response.uri.host) { |http| http.head response.uri.path }

如果你想保留响应代码的历史,你可以试试这个。这会保留调用的最后 5 个响应代码,get_response并通过Net::HTTP.history方法公开它们。

module Net
  class << HTTP
    alias_method :_get_response, :get_response

    def get_response *args, &block
      resp = _get_response *args, &block
      @history = (@history || []).push(resp.code).last 5
      resp
    end

    def history 
      @history || []
    end
  end
end

(使用场景我不完全了解,请适应你的需求)

于 2013-11-01T19:30:27.820 回答