Customizing HTTP Request Headers

Problem

When you make an HTTP request, you want to specify custom HTTP headers like " User-Agent" or " Accept-Language".

Solution

Pass in a Hash of header values to Net::HTTP#get or Net::HTTP#post:

require et/http require uri #A simple wrapper method that accepts either strings or URI objects #and performs an HTTP GET. module Net class HTTP def HTTP.get_with_headers(uri, headers=nil) uri = URI.parse(uri) if uri.respond_to? :to_str start(uri.host, uri.port) do | http| return http.get(uri.path, headers) end end end end #Lets get a web page in German. res = Net::HTTP.get_with_headers(http://www.google.com/, { Accept-Language => de}) #Check a bit of the body to make sure its really in German. s = res.body.size res.body[s-200..s-140] # => "ngebote</a> - <a href=/intl/de/about.html>Alles 374ber Google

Discussion

Usually you can retrieve the web pages you want without specifying any custom HTTP headers. As you start performing more complicated interactions with web servers, youll find yourself customizing the headers more.

For instance, if you write a web spider or client, youll want it to send a " User-Agent" header on every request, identifying itself to the web server. Unlike the HTTP client libraries for other programming languages, the net/http library doesn send a "User-Agent" header by default; its your reponsibility to send one.

Net::HTTP.get_with_headers(url, {User-Agent => Ruby Web Browser v1.0})

You can often save bandwidth (at the expense of computer time) by sending an "Accept-Encoding" header, requesting that a web server compress data before sending it to you. Gzip compression is the most common way a server compresses HTTP response data; you can reverse it with Rubys zlib library:

uncompressed = Net::HTTP.get_with_headers(http://www.cnn.com/) uncompressed.body.size # => 65150 gzipped = Net::HTTP.get_with_headers(http://www.cnn.com/, {Accept-Encoding => gzip}) gzipped[Content-Encoding] # => "gzip" gzipped.body.size # => 14600 require zlib require stringio body_io = StringIO.new(gzipped.body) unzipped_body = Zlib::GzipReader.new(body_io).read() unzipped_body.size # => 65150

If you want to build up a HTTP request with multiple values for the same HTTP header, you can construct a Net:: HTTP::Get (or Net::HTTP::Post) object and call the add_field method multiple times. The example in the Solution used the " Accept-Language" header to request a document in a specific language. The following code fetches the same URL, but its "Accept-Language" header indicates that it will accept a document written in any of four different dialects:

uri = URI.parse(http://www.google.com/) request = Net::HTTP::Get.new(uri.path) [en_us, en, en_gb, ja].each do |language| request.add_field(Accept-Language, language) end request[Accept-Language] # => "en_us, en, en_gb, ja" Net::HTTP.start(uri.host, uri.port) do |http| response = http.request(request) # … process the HTTPResponse object here end

See Also

Категории