Apache::Request - Methods for dealing with client request data |
Apache::Request - Methods for dealing with client request data
use Apache::Request (); my $apr = Apache::Request->new($r);
Apache::Request is a subclass of the Apache class, which adds methods
for parsing GET requests and POST requests where Content-type
is one of application/x-www-form-urlencoded or
multipart/form-data. See the libapreq(3)
manpage for more details.
The interface is designed to mimic CGI.pm 's routines for parsing query parameters. The main differences are
Apache::Request::new
takes an Apache object as (second) argument.-attr => $val
-type arguments are not supported.
Create a new Apache::Request object with an Apache request_rec object:
my $apr = Apache::Request->new($r);
All methods from the Apache class are inherited.
The following attributes are optional:
my $apr = Apache::Request->new($r, POST_MAX => 1024); my $status = $apr->parse;
if ($status) { my $errmsg = $apr->notes("error-notes"); ... return $status; }
my $apr = Apache::Request->new($r, DISABLE_UPLOADS => 1); my $status = $apr->parse;
if ($status) { my $errmsg = $apr->notes("error-notes"); ... return $status; }
my $apr = Apache::Request->new($r, TEMP_DIR => "/home/httpd/tmp"); my $upload = $apr->upload('file'); $upload->link("/home/user/myfile") || warn "link failed: $!";
Note: The standard C library function tempnam()
is used to define the
file to be used, and it may well prefer to look for some other temporary
directory, specified by an environment variable in the environment of the
user that Apache is running as, in preference to the one passed to it.
For example, Microsoft's tempnam()
implementation will look for a TMP
environment variable first; glibc's version looks for TMPDIR first. The
TEMP_DIR specified here is generally only used if the relevant environment
variable is not set, or the directory specified by it does not exist.
Refer to your system's C library documentation for the full details on your
platform.
my $transparent_hook = sub { my ($upload, $buf, $len, $hook_data) = @_; warn "$hook_data: got $len bytes for " . $upload->name; };
my $apr = Apache::Request->new($r, HOOK_DATA => "Note", UPLOAD_HOOK => $transparent_hook, ); $apr->parse;
The instance()
class method allows Apache::Request to be a singleton.
This means that whenever you call Apache::Request->instance()
within a
single request you always get the same Apache::Request object back.
This solves the problem with creating the Apache::Request object twice
within the same request - the symptoms being that the second
Apache::Request object will not contain the form parameters because
they have already been read and parsed.
my $apr = Apache::Request->instance($r, DISABLE_UPLOADS => 1);
Note that instance()
call will take the same parameters as the above
call to new()
, however the parameters will only have an effect the
first time instance()
is called within a single request. Extra
parameters will be ignored on subsequent calls to instance()
within
the same request.
Subrequests receive a new Apache::Request object when they call
instance()
- the parent request's Apache::Request object is not copied
into the subrequest.
Also note that it is unwise to use the parse()
method when using
instance()
because you may end up trying to call it twice, and
detecting errors where there are none.
The parse method does the actual work of parsing the request. It is called for you by the accessor methods, so it is not required but can be useful to provide a more user-friendly message should an error occur:
my $r = shift; my $apr = Apache::Request->new($r);
my $status = $apr->parse; unless ($status == OK) { $apr->custom_response($status, $apr->notes("error-notes")); return $status; }
Get or set request parameters (using case-insensitive keys) by
mimicing the OO interface of CGI::param
. Unlike the CGI.pm version,
Apache::Request's param method is very fast- it's now quicker than even
mod_perl's native Apache->args method. However, CGI.pm's
-attr => $val
type arguments are not supported.
# similar to CGI.pm
my $value = $apr->param('foo'); my @values = $apr->param('foo'); my @params = $apr->param;
# the following differ slightly from CGI.pm
# assigns multiple values to 'foo' $apr->param('foo' => [qw(one two three)]);
# returns ref to underlying apache table object my $table = $apr->param; # identical to $apr->parms - see below
Get or set the underlying apache parameter table of the Apache::Request
object. When invoked without arguments, parms
returns a reference
to an Apache::Table object that is tied to the Apache::Request
object's parameter table. If called with an Apache::Table reference
as as argument, the Apache::Request object's parameter table is
replaced by the argument's table.
# $apache_table references an Apache::Table object $apr->parms($apache_table); # sets $apr's parameter table
# returns ref to Apache::Table object provided by $apache_table my $table = $apr->parms;
Returns a single Apache::Upload object in a scalar context or all Apache::Upload objects in a list context:
my $upload = $apr->upload; my $fh = $upload->fh; my $lines = 0; while(<$fh>) { ++$lines; ... }
An optional name parameter can be passed to return the Apache::Upload object associated with the given name:
my $upload = $apr->upload($name);
The Apache::Request class cannot be subclassed directly because its constructor method does not bless new objects into the invocant class. Instead, it always blesses them into the Apache::Request class itself.
However, there are two main ways around this.
One way is to have a constructor method in your subclass that invokes the superclass constructor method and then re-blesses the new object into itself before returning it:
package MySubClass; use Apache::Request; our @ISA = qw(Apache::Request); sub new { my($class, @args) = @_; return bless $class->SUPER::new(@args), $class; }
The other way is to aggregate and delegate: store an Apache::Request object in each instance of your subclass, and delegate any Apache::Request methods that you are not overriding to it:
package MySubClass; use Apache::Request; sub new { my($class, @args) = @_; return bless { r => Apache::Request->new(@args) }, $class; } sub AUTOLOAD { my $proto = shift; return unless ref $proto; our $AUTOLOAD; my $name = $AUTOLOAD; $name =~ s/^.*:://; return $proto->{r}->$name(@_); }
A fancier AUTOLOAD()
subroutine could be written to handle class methods too if
required, but we leave that as an exercise for the reader because in fact the
Apache::Request class provides some magic that makes the aggregate/delegate
solution much easier.
If the instances of your subclass are hash references then you can actually inherit from Apache::Request as long as the Apache::Request object is stored in an attribute called ``r'' or ``_r''. (The Apache::Request class effectively does the delegation for you automagically, as long as it knows where to find the Apache::Request object to delegate to.)
Thus, the second example above can be simplified as:
package MySubClass; use Apache::Request; our @ISA = qw(Apache::Request); sub new { my($class, @args) = @_; return bless { r => Apache::Request->new(@args) }, $class; }
The name of the filefield parameter:
my $name = $upload->name;
The filename of the uploaded file:
my $filename = $upload->filename;
The filehandle pointing to the uploaded file:
my $fh = $upload->fh; while (<$fh>) { ... }
The size of the file in bytes:
my $size = $upload->size;
The additional header information for the uploaded file. Returns a hash reference tied to the Apache::Table class. An optional key argument can be passed to return the value of a given header rather than a hash reference. Examples:
my $info = $upload->info; while (my($key, $val) = each %$info) { ... }
my $val = $upload->info("Content-type");
Returns the Content-Type for the given Apache::Upload object:
my $type = $upload->type; #same as my $type = $upload->info("Content-Type");
Upload objects are implemented as a linked list by libapreq; the next method provides an alternative to using the Apache::Request upload method in a list context:
for (my $upload = $apr->upload; $upload; $upload = $upload->next) { ... }
#functionally the same as:
for my $upload ($apr->upload) { ... }
Provides the name of the spool file. This method is reserved for debugging purposes, and is possibly subject to change in a future version of Apache::Request.
To avoid recopying the spool file on a *nix-like system, link will create a hard link to it:
my $upload = $apr->upload('file'); $upload->link("/path/to/newfile") or die sprintf "link from '%s' failed: $!", $upload->tempname;
Typically the new name must lie on the same file system as the
spool file. Check your system's link(2)
manpage for details.
libapreq(3), Apache::Table(3)
This interface is based on the original pure Perl version by Lincoln Stein.
Doug MacEachern, updated for v1.0 by Joe Schaefer, updated for v1.2 by Steve Hay.
Apache::Request - Methods for dealing with client request data |