Ruby Net :: HTTP - 遵循301重定向

时间:2011-08-26 20:27:38

标签: ruby

我的用户提交了网址(混合在mixcloud.com上),我的应用程序使用它们来执行网络请求。

好网址会返回200状态代码:

uri = URI.parse("http://www.mixcloud.com/ErolAlkan/hard-summer-mix/")
request = Net::HTTP.get_response(uri)(
#<Net::HTTPOK 200 OK readbody=true>

但是如果你忘记了斜杠,那么我们的其他好的网址会返回301:

uri = "http://www.mixcloud.com/ErolAlkan/hard-summer-mix"
#<Net::HTTPMovedPermanently 301 MOVED PERMANENTLY readbody=true> 

404的情况也是如此:

# bad path returns a 404
"http://www.mixcloud.com/bad/path/" 
# bad path minus trailing slash returns a 301
"http://www.mixcloud.com/bad/path"
  1. 如何“向下钻取”301以查看是否需要我们使用有效资源或错误页面?
  2. 是否有工具可以全面概述特定域可能适用于其网址的规则?

5 个答案:

答案 0 :(得分:47)

如果您没有完全按照Web服务器的预期输入URL,那么301重定向是相当常见的。它们的发生频率比您想象的要频繁,您在浏览时通常不会注意到它们,因为浏览器会自动为您完成所有操作。

有两种选择:

1:使用open-uri

open-uri自动处理重定向。所以你需要做的就是:

require 'open-uri' 
...
response = open('http://xyz...').read

如果您在HTTP和HTTPS之间重定向时遇到问题,请查看解决方案:
Ruby open-uri redirect forbidden

2:使用Net::HTTP

处理重定向
def get_response_with_redirect(uri)
   r = Net::HTTP.get_response(uri)
   if r.code == "301"
     r = Net::HTTP.get_response(URI.parse(r.header['location']))
   end
   r
end

如果你想变得更聪明,你可以尝试在获得404响应时添加或删除丢失的反斜杠到URL。你可以通过创建像get_response_smart这样的方法来做到这一点,除了重定向之外,它还可以处理这个URL。

答案 1 :(得分:5)

我无法弄清楚如何评论已接受的答案(此问题可能会被关闭),但我应该注意r.header现已过时,因此r.header['location']应替换为{{ 1}}(每https://stackoverflow.com/a/6934503/1084675

答案 2 :(得分:3)

以下是我提出的代码(来自不同的示例),如果重定向太多(请注意,ensure_success是可选的),将会挽救:

require "net/http"
require "uri"
class Net::HTTPResponse
  def ensure_success
    unless kind_of? Net::HTTPSuccess
      warn "Request failed with HTTP #{@code}"
      each_header do |h,v|
        warn "#{h} => #{v}"
      end
      abort
    end
  end
end
def do_request(uri_string)
  response = nil
  tries = 0
  loop do
    uri = URI.parse(uri_string)
    http = Net::HTTP.new(uri.host, uri.port)
    request = Net::HTTP::Get.new(uri.request_uri)
    response = http.request(request)
    uri_string = response['location'] if response['location']
    unless response.kind_of? Net::HTTPRedirection
      response.ensure_success
      break
    end
    if tries == 10
      puts "Timing out after 10 tries"
      break
    end
    tries += 1
  end
  response
end

答案 3 :(得分:3)

rest-client遵循require 'rest-client' RestClient.get 'http://example.com/resource' begin RestClient.post('http://example.com/redirect', 'body') rescue RestClient::MovedPermanently, RestClient::Found, RestClient::TemporaryRedirect => err err.response.follow_redirection end 请求的重定向,无需任何其他配置。它非常好用。

  
      
  • 对于200到207之间的结果代码,将返回RestClient :: Response
  •   
  • 对于结果代码301,302或307,如果请求是GET或HEAD,则将遵循重定向
  •   
  • 对于结果代码303,将遵循重定向并将请求转换为GET
  •   

用法示例:

ng-animate

rest-client README还提供了一个关于POST请求重定向的示例:

angular

答案 4 :(得分:1)

不确定是否有人正在寻找这个确切的解决方案,但如果您尝试下载图像http / https并将其存储到变量

require 'open_uri_redirections'

require 'net/https'

web_contents  = open('file_url_goes_here', :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE, :allow_redirections => :all) {|f| f.read }
puts web_contents