Ruby Net::HTTP - following 301 redirects

前端 未结 5 747
时光说笑
时光说笑 2020-12-05 04:36

My users submit urls (to mixes on mixcloud.com) and my app uses them to perform web requests.

A good url returns a 200 status code:

         


        
相关标签:
5条回答
  • 2020-12-05 04:59

    Not sure if anyone is looking for this exact solution, but if you are trying to download an image http/https and store it to a variable

    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
    
    0 讨论(0)
  • 2020-12-05 05:00

    Here is the code I came up with (derived from different examples) which will bail out if there are too many redirects (note that ensure_success is optional):

    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
    
    0 讨论(0)
  • 2020-12-05 05:01

    I can't figure out how to comment on the accepted answer (this question might be closed), but I should note that r.header is now obsolete, so r.header['location'] should be replaced by r['location'] (per https://stackoverflow.com/a/6934503/1084675 )

    0 讨论(0)
  • 2020-12-05 05:12

    301 redirects are fairly common if you do not type the URL exactly as the web server expects it. They happen much more frequently than you'd think, you just don't normally ever notice them while browsing because the browser does all that automatically for you.

    Two alternatives come to mind:

    1: Use open-uri

    open-uri handles redirects automatically. So all you'd need to do is:

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

    If you have trouble redirecting between HTTP and HTTPS, then have a look here for a solution:
    Ruby open-uri redirect forbidden

    2: Handle redirects with 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['location']))
       end
       r
    end
    

    If you want to be even smarter you could try to add or remove missing backslashes to the URL when you get a 404 response. You could do that by creating a method like get_response_smart which handles this URL fiddling in addition to the redirects.

    0 讨论(0)
  • 2020-12-05 05:19

    rest-client follows the redirections for GET and HEAD requests without any additional configuration. It works very nice.

    • for result codes between 200 and 207, a RestClient::Response will be returned
    • for result codes 301, 302 or 307, the redirection will be followed if the request is a GET or a HEAD
    • for result code 303, the redirection will be followed and the request transformed into a GET

    example of usage:

    require 'rest-client'
    
    RestClient.get 'http://example.com/resource'
    

    The rest-client README also gives an example of following redirects with POST requests:

    begin
      RestClient.post('http://example.com/redirect', 'body')
    rescue RestClient::MovedPermanently,
           RestClient::Found,
           RestClient::TemporaryRedirect => err
      err.response.follow_redirection
    end
    
    0 讨论(0)
提交回复
热议问题