home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Practical mod_perlPractical mod_perlSearch this book

A.2. Reusing Data from POST Requests

What happens if you need to access the POST ed data more than once. For example, suppose you need to reuse it in subsequent handlers of the same request? POST ed data comes directly from the socket, and at the low level data can be read from a socket only once. You have to store it to make it available for reuse.

But what do you do with large multipart file uploads? Because POST ed data is not all read in one clump, it's a problem that's not easy to solve in a general way. A transparent way to do this is to switch the request method from POST to GET and store the POST data in the query string. The handler in Example A-1 does exactly that.

Example A-1. Apache/POST2GET.pm

package Apache::POST2GET;
use Apache::Constants qw(M_GET OK DECLINED);

sub handler {
    my $r = shift;
    return DECLINED unless $r->method eq "POST";
    $r->args(scalar $r->content);
    $r->method('GET');
    $r->method_number(M_GET);
    $r->headers_in->unset('Content-length');
    return OK;
}
1;

In httpd.conf add:

PerlInitHandler Apache::POST2GET

or even this:

<Limit POST>
    PerlInitHandler Apache::POST2GET
</Limit>

to save a few more cycles. This ensures that the handler will be called only for POST requests.

Be aware that this will work only if the POST ed data doesn't exceed the maximum allowed size for GET requests. The default maximum size is 8,190 bytes, but it can be lowered using the LimitRequestLine configuration directive.

Effectively, this trick turns the POST request into a GET request internally. Now when a module such as CGI.pm or Apache::Request parses the client data, it can do so more than once, since $r->args doesn't go away (unless you make it go away by resetting it).

If you are using Apache::Request, it solves this problem for you with its instance( ) class method, which 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.



Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.