Home > Articles > Web Development > Perl

  • Print
  • + Share This
This chapter is from the book

This chapter is from the book

Setting Error Headers

You want to set server response headers that will persist on errors or internal redirects.

Technique

Set the headers with the err_headers_out() method instead of headers_out().

use My::Utils; # some fictional utility package

sub handler {

 my $r = shift;

 # Invalidate the session on error.
 unless (My::Utils::validate_user($r->user)) {
  $r->err_headers_out->set('Set-Cookie' => 'session=expired');
  return FORBIDDEN;
 }

 # Continue along...

}

Comments

Apache actually keeps two separate server response header tables in the request record—one for normal response headers and one for error headers. The difference between them is that the error headers are sent to the client even (not only) on an error response. Recall from the previous recipe that, to Apache, an error response is anything other than OK, DECLINED, or DONE.

The error headers are manipulated using the err_headers_out() method from the Apache class, which has the same interface as the headers_in() and headers_out() methods described previously. They are particularly useful for influencing browser behavior, such as creating cookies that persist across errors and can force a user to re-authenticate, as in the preceding example.

There are a few things to understand when it comes to manipulating error headers. First, it is important to note that unlike when sending content and returning OK, you should not call $r->send_http_header() before returning an error status. When Apache receives an error return status, such as SERVER_ERROR, REDIRECT, or AUTH_REQUIRED it will automatically send the proper set of headers, so there is no need for you to worry about it.

The second point to remember is that the error headers are always sent, which makes the name somewhat misleading. Don't fall into the trap of doing something like:

# This is a bogus example!
# err_headers_out() takes precedence over headers_out()!

# Capture errors with a cookie...
$r->err_headers_out->set('Set-Cookie' => 'error=whoops');

# ... otherwise set the session.
$r->headers_out->set('Set-Cookie' => 'session=$sessionid');

Then, later in another handler, trying to capture errors with

if ($cookiejar{$cookie}->name eq "error") {
 # Do some error processing.
}

Here the end result will be that every request will contain the error cookie, making it rather meaningless for distinguishing errors.

If you take a moment to think about the error header mechanism, you might be prompted to question the standard practice of setting the Location header for a REDIRECT response via headers_out()

$r->headers_out->set(Location => 'http://www.example.com/entry.html');
return REDIRECT;

and use err_headers_out() instead. As it turns out, the Location header is handled as a special case when an error occurs. Apache will first look for the Location header in the headers_out table in the request record, then look in the err_headers_out table if the headers_out table yielded no results.

  • + Share This
  • 🔖 Save To Your Account