如何使用NET:HTTP获取重定向的状态代码?

时间:2013-11-01 18:33:25

标签: ruby redirect net-http

与“getting the status code of a HTTP redirected page”类似,但是使用NET :: HTTP而不是curb我正在向将重定向的页面发出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,我也会收到票证过期的错误

2 个答案:

答案 0 :(得分:1)

Net::HTTP documentation有示例代码,展示了如何处理重定向。你试过吗?它应该可以很容易地进入重定向机制并获取状态以供日后使用。

以下是他们的例子:

  

重定向后

     

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

     

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

     

使用案例陈述,您可以正确处理各种类型的答案:

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>

答案 1 :(得分:0)

如果只是在没有“消费”你的网址的情况下发出HTTP HEAD请求就足够了(这通常是对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 }

如果您想保留回复代码的历史记录,可以试试这个。这会保留调用get_response的最后5个响应代码,并通过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

(我没有完全了解使用方案,因此要适应您的需求)