Home > Articles > Web Development > Perl

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

This chapter is from the book

Manipulating Headers with Multiple Like Fields

You want to manipulate headers that have multiple like header fields, but assigning them to a hash removes all but the last value.

Technique

Use the Apache::Table class to access your headers.

# Take a peek at what we are going to set.
my @cookies = $r->headers_out->get('Set-Cookie');

Comments

Calling headers_in() or headers_out() and assigning the return value to a hash has its limitations, especially when dealing with headers that may have more than one entry in the table, such as Set-Cookie. As we have mentioned a few times, calling either of these methods in a scalar context returns an Apache::Table object, which has its own set of methods— in particular, the get() method, which returns a single value in a scalar context or a list of values in a list context.

Actually, the Apache::Table class is an important one to be familiar with, in part because it is the underlying class for many methods, including methods for manipulating some fields of the Apache request record:

  • err_headers_out()
  • headers_in()
  • headers_out()
  • notes()
  • subprocess_env()

as well as these additional methods:

  • dir_config() from the Apache class
  • info() from the Apache::Upload class
  • param() from the Apache::Request class

The Apache::Table class offers a consistent, powerful interface for manipulating the data beneath each of these methods. It ties into Apache's internal table structure, which allows for things such as headers to be stored in a case-insensitive manner with multiple values per key. This comes in handy when joining the case-insensitive HTTP protocol with case-sensitive Perl, making calls such as

my $encodings = $r->headers_in->get('accept-encoding');

successful, no matter how the user agent capitalized the header.

Apache::Table has only a handful of methods:

  • add()
  • clear()
  • do()
  • get()
  • merge()
  • new()
  • set()
  • unset()

of which you will probably only use a few in everyday programming. Although most should be self-explanatory, do() is a unique method that allows you to iterate over the entire table and uses a special idiom.

# Most user agents string multiple cookies together
# using ";" as the separator. Break these cases apart 
# so each appears as a separate entry.
$r->headers_in->do(sub {
 # The key/value pair is passed as the argument list.
 my ($key, $value) = @_;

 if ($key =~ m/Cookie/) {
  print map { "Cookie => $_\n" } split /;\s?/, $value;
 }
 else {
  print " $key => $value\n";
 }
 # do() exits on false, so we add this as good programming practice.
 1;
});

Using the various Apache::Table methods to access mod_perl data structures has many advantages. As we demonstrated in Recipe 2.14, the PerlAddVar construct is made possible through the use of the Apache::Table framework and the $r->dir_config->get() interface, which allows programmers to access an entire array of values set within a configuration. Aside from typical uses like this, it pays to take a moment and contemplate the full range of power that you have available through the Apache::Table methods. For instance, although setting an outgoing header using the following might seem perfectly intuitive:

$r->headers_out->set('Set-Cookie' => 'punishment=plank');

you can also do things like

# Add values to our configuration.
$r->dir_config->set(Filter => 'On');

which is equivalent to setting

PerlSetVar Filter On

in your httpd.conf for use by later handlers in the request. Cool.

  • + Share This
  • 🔖 Save To Your Account