Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

mod_perl Apache::Request vs Apache->request

by drfrog (Deacon)
on Jan 21, 2004 at 21:56 UTC ( [id://323035]=perlquestion: print w/replies, xml ) Need Help??

drfrog has asked for the wisdom of the Perl Monks concerning the following question:

while i understand the difference between these two i am unsure how to handle these back and forth. let me explain:

I have an upload module with the handler using an Apache::Request

my $r = Apache::Request->new( shift, POST_MAX => 10 * 1024 * 1024, # in bytes, so 10M DISABLE_UPLOADS => 0 );
later on i want to send all the info recieved from a file to another module that inserts this information into a database table

rather than pass through a LWP::Simple::get call i would like to call the subroutine that handles the logic directly like so:

&MYMod::Add::Add($r);
BUT i have the above subroutine pulling in the Apache->request object if through MYMod::Add::handler

so i tried something like this in my upload module

my $r = Apache->request; # Standard stuff, with added options... my $apr = Apache::Request->new( $r, POST_MAX => 10 * 1024 * 1024, # in bytes, so 10M DISABLE_UPLOADS => 0 );
and then

&MYMod::Add::Add($r);
but this just borks out the upload procedure and nothing get processed, whereas if i just pass in the Apache::Request it doesnt process the parameters correctly

can anyone explain the finesse i am messing up?

Replies are listed 'Best First'.
Re: mod_perl Apache::Request vs Apache->request
by cleverett (Friar) on Jan 22, 2004 at 11:32 UTC
    Well, mod_perl doesn't work that way. Everything in mod_perl gets structured in accordance to the Apache lifecycle, and that handlers are tied to the directory, file or location sections in your httpd.conf. So you can't just feed to another module and expect it to automagically figure out what to do woth it.

    You almost certainly want to use inheritance instead.

    package My::Upload; sub Upload { my ($class, $apr) = @_; $class->Add($_) foreach $apr->upload; } sub Add { my ($class, $apr) = @_; ... } package My::Doohickey; use base qw/My::Upload/; sub handler ($$) { my ($class, $r) = @_; my $apr = Apache::Request->instance($r, POST_MAX => 10*1024*1024, DISABLE_UPLOADS => 0); $class->Upload($apr) if $apr->upload; ... return OK; }

    Notes:

    1. Using Apache::Request->instance() reuses a previously created Apache::Request object if you've created one for the current request. Only problem is that it ignores the parameters after $r after the first invocation.

    2. If you start out with something like:

    sub handler ($$) { my ($class, $r) = @_; my $apr = Apache::Request->instance($r, POST_MAX => 10*1024*1024, DISABLE_UPLOADS => 0); ...

    That will put the module name in $class, the Apache object in $r, and an Apache::Request object in $apr.

    3. If the browser is on a dialup line, that server process will wait damn near forever for the uploaded file. This would be a cheap DoS attack on your server: just do 10 MB uploads to your server until your server starts thrashing. I generally limit uploads to the smallest I can get away with, and use a proxy Apache with a smaller footprint front end to buffer the requests.

    HTH

    update:As I think about it, something like My::Mod::Add->handler($r) might work. But very likely it won't ... I've never tried it and I have more interesting experiments to perform.

Re: mod_perl Apache::Request vs Apache->request
by edoc (Chaplain) on Jan 21, 2004 at 22:36 UTC

    I think I know where you're at, and you could probably work around it in some way, but I would sugest modularising your code further.. Your upload module should be just that, not a handler. It should take $r as an arg and operate on that. Then you can call that module from any handler that needs it.

    ps. You should also be using Apache::Request->instance but I'm not sure that that will solve your immediate problem.

    cheers,

    J

      ok i have more time now to show more code!

      first listing is the Add which should be able to be accessed by either the second listing or the location handler like in the third listing
      **-- listing 1----** package MyMod::Add; use strict; use warnings; sub handler { my $r = Apache->request; my %args = $r->args; &Add($r); } sub Add { my $r = shift; my %args = $r->args; ..... } **---listing 2----** package MyMod::Uploads; use strict; use warnings; use MyMod::Add; use LWP::Simple; use URI::Escape; sub handler { # Standard stuff, with added options... my $r = Apache::Request->new( shift, POST_MAX => 10 * 1024 * 1024, # in bytes, + so 10M DISABLE_UPLOADS => 0 ); if ($r->upload){ upload($r); } } sub upload { foreach my $upload ( $r->upload ) { ##parse upload &MyMod::Add::Add($r); } } **---listing 3---** in httpd.conf: <Location /add> SetHandler perl-script PerlHandler MyMod::Add </Location>
      how can i do both? i know its possible without the upload scenario
Re: mod_perl Apache::Request vs Apache->request
by Fletch (Bishop) on Jan 22, 2004 at 14:53 UTC

    Maybe you could use the notes() or pnotes() methods to attach your extra information to the request and have your module retrieve it from there.

      Umm, but how does he switch himself to the module that does the work? internal_redirect?

        Just call it and pass it the request. A handler is just a sub (and method handlers are just instance methods). There's nothing that says you can't delegate. And if the handler in question could be called directly, have it use the instance() method that Apache::Request provides that will just return the same object no matter how many times during a request it gets called (see the A::R docs for more info).

        package Foo; use Apache::Request; use Apache::Constants qw( OK ); sub handler { my $r = Apache::Request->new( shift ); $r->pnotes( Foo => "Bar" ); return Bar::handler( $r ); } package Bar; sub handler { my $r = shift; $r->send_http_header( "text/plain" ); print "uri is: ", $r->uri(), "\n"; print "Foo is: ", $r->pnotes()->{Foo}, "\n"; return OK; } 1; __END__ <Directory /usr/local/apache/htdocs/foo> SetHandler perl-script PerlHandler Foo </Directory> uri is: /foo Foo is: Bar

        Update: Ahh, I actually looked back up the thread and saw the sample code that looks similar to this. It looks like you should be using the instance() method in both handlers and that'll always give you back the same A::R object as a singleton. Teach me to read back up the whole thread rather than just looking at replies. %)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://323035]
Approved by Roger
Front-paged by rlb3
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (3)
As of 2024-04-25 22:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found