Setting Cookies and Other HTTP Response Headers

Credit: Mauro Cicio

Problem

You e writing a CGI program and you want to customize the HTTP headers you send in response to a request. For instance, you may want to set a client-side cookie so that you can track state between HTTP requests.

Solution

Pass a hash of headers into the CGI#out method that creates the HTTP response. Each key of the hash is the name of a header to set, or a special value (like cookie), which the CGI class knows how to interpret.

Heres a CGI script that demonstrates how to set some response headers, including a cookie and a custom HTTP header called "Recipe Name".

First we process any incoming cookie. Every time you hit this CGI, the value stored in your cookie will be incremented, and the date of your last visit will be reset.

#!/usr/bin/ruby # headers.cgi require "cgi" cgi = CGI.new("html3") # Retrieve or create the "rubycookbook" cookie cookie = cgi. cookies[ ubycookbook] cookie = CGI::Cookie.new( ubycookbook, hits=0, "last=#{Time.now}") if cookie.empty? # Read the values in the cookie for future use hits = cookie.value[0].split(=)[1] last = cookie.value[1].split(=)[1] # Set new values in the cookie cookie.value[0] = "hits=#{hits.succ}" cookie.value[1] = "last=#{Time.now}"

Next, we build a hash of HTTP headers, and send the headers by passing the hash into CGI#out. We then generate the output document. Since the end user doesn usually see the HTTP headers they e served, well make them visible by repeating them in the output document (Figure 14-1):

# Create a hash of HTTP response headers. header = { status => OK, cookie => [cookie], Refresh => 2, Recipe Name => Setting HTTP Response Headers, server => ENV[SERVER_SOFTWARE] } cgi.out(header) do cgi.html(PRETTY => ) do cgi.head { cgi.title { Setting HTTP Response Headers } } + cgi.body do cgi.p(Your headers:) + cgi.pre{ cgi.header(header) } + cgi.pre do "Number of times your browser hit this cgi: #{hits} "+ "Last connected: #{last}" end end end end

Figure 14-1. This CGI lets you see the response headers, including the cookie

The Refresh header makes your web browser refresh the page every two seconds. You can visit this CGI once and watch the number of hits (stored in the client-side cookie) start to mount up.

Discussion

An HTTP Response consists of two sections (a header section and a body section) separated by a blank line. The body contains the document to be rendered by the browser (usually an HTML page) and the header carries metadata: information about the connection, the response, and the document itself. The CGI#out method takes a hash representing the HTTP headers, and a code block that generates the body.

CGI#out recognizes a few special values that make it easier to set custom headers. For instance, the header hash in the example above maps the key "cookie" to a CGI::Cookie object. CGI#out knows enough to turn cookie into the standard HTTP header Set-Cookie, and to transform the CGI::Cookie object into a string rendition.

If CGI#out doesn know about a certain key, it simply sends it as an HTTP header, as-is. CGI#out has no special knowledge of our "Refresh" and "Recipe Name" headers, so it writes them verbatim to the HTTP response. "Refresh" is a standard HTTP response header recognized by most web browsers; "Recipe Name" is a header I made up for this recipe, and web browsers should ignore it.

See Also

Категории