This page contains automated test results for code from O'Reilly's Ruby Cookbook. If this code looks interesting or useful, you might want to buy the whole book.
A Real-World HTTP Client | ||
---|---|---|
Code | Expected | Actual |
require 'net/http' require 'set' class Net::HTTPResponse attr_accessor :final_uri end module Net begin require 'net/https' HTTPS_SUPPORTED = true rescue LoadError HTTPS_SUPPORTED = false end class HTTP # Makes an HTTP request and returns the HTTPResponse object. # Args: :proxy_host, :proxy_port, :action (:get, :post, etc.), # :data (for :post action), :max_redirects. def HTTP.fetch(uri, args={}.freeze, &before_fetching) # Process the arguments with default values uri = URI.parse(uri) unless uri.is_a? URI proxy_host = args[:proxy_host] proxy_port = args[:proxy_port] || 80 action = args[:action] || :get data = args[:data] max_redirects = args[:max_redirects] || 10 # Use a proxy class to create the request object proxy_class = Proxy(proxy_host, proxy_port) request = proxy_class.new(uri.host, uri.port) request.use_ssl = true if HTTPS_SUPPORTED and uri.scheme == 'https' yield request if block_given? response = request.send(action, uri.path, data) urls_seen = args[:_urls_seen] || Set.new if response.is_a?(Net::HTTPRedirection) # Redirect if urls_seen.size < max_redirects && response['Location'] urls_seen << uri new_uri = URI.parse(response['Location']) break if urls_seen.member? new_uri # Infinite redirect loop # Request the new location just as we did the old one. new_args = args.dup puts "Redirecting to #{new_uri}" if $DEBUG new_args[:_urls_seen] = urls_seen response = HTTP.fetch(new_uri, new_args, &before_fetching) end else # No redirect response.final_uri = uri end return response end end end response = Net::HTTP.fetch("http://google.com/") puts "#{response.final_uri} body is #{response.body.size} bytes." |
http://www.google.com/ body is 2444 bytes. |
http://www.google.com/ body is 2444 bytes. |
response = Net::HTTP.fetch("http://google.com/", :proxy_host => "164.xxx.xxx.xxx") puts "#{response.final_uri} body is #{response.body.size} bytes." |
http://www.google.com.sg/ body is 2853 bytes. |
SocketError: getaddrinfo: Name or service not known from /usr/lib/ruby/1.8/net/http.rb:562:in `initialize' from /usr/lib/ruby/1.8/net/http.rb:562:in `connect' from /usr/lib/ruby/1.8/timeout.rb:48:in `timeout' from /usr/lib/ruby/1.8/timeout.rb:76:in `timeout' from /usr/lib/ruby/1.8/net/http.rb:562:in `connect' from /usr/lib/ruby/1.8/net/http.rb:555:in `do_start' from /usr/lib/ruby/1.8/net/http.rb:544:in `start' from /usr/lib/ruby/1.8/net/http.rb:1031:in `request' from /usr/lib/ruby/1.8/net/http.rb:771:in `get' from (irb):30:in `fetch' from (irb):52 from :0 http://www.google.com/ body is 2444 bytes. |
response = Net::HTTP.fetch("https://paypal.com/", :proxy_host => "209.xxx.xxx.xxx") do |request| request.ca_path = "/etc/ssl/certs/" request.verify_mode = OpenSSL::SSL::VERIFY_PEER end puts "#{response.final_uri} body is #{response.body.size} bytes." |
https://paypal.com/us/ body is 16978 bytes. |
SocketError: getaddrinfo: Name or service not known from /usr/lib/ruby/1.8/net/http.rb:562:in `initialize' from /usr/lib/ruby/1.8/net/http.rb:562:in `connect' from /usr/lib/ruby/1.8/timeout.rb:48:in `timeout' from /usr/lib/ruby/1.8/timeout.rb:76:in `timeout' from /usr/lib/ruby/1.8/net/http.rb:562:in `connect' from /usr/lib/ruby/1.8/net/http.rb:555:in `do_start' from /usr/lib/ruby/1.8/net/http.rb:544:in `start' from /usr/lib/ruby/1.8/net/http.rb:1031:in `request' from /usr/lib/ruby/1.8/net/http.rb:771:in `get' from (irb):30:in `fetch' from (irb):55 from :0 http://www.google.com/ body is 2444 bytes. |