Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Re: Subclassing Apache::Request?

by ikegami (Patriarch)
on Aug 11, 2004 at 03:14 UTC ( [id://381849]=note: print w/replies, xml ) Need Help??


in reply to Subclassing Apache::Request?

Replies are listed 'Best First'.
Re^2: Subclassing Apache::Request?
by tadamec (Beadle) on Aug 11, 2004 at 03:40 UTC

    I fail to see much difference between the two, actually. My subclassing example was taken from the Apache::Request man page under their subclassing section.

    When I modified my Apache::Request object as was in the docs, it still broke exactly the same.

    I guess I don't understand how I should be doing this. How do I get the server to return my new object instead of a generic Apache object. Or, how do I get the server to return my object blessed as an Apache object, instead of returning a generic Apache::Request object?

    I'm even more confused now than when I started.

      What you are failing to understand here is that your handler is not an object, it is just a class. In fact, it's not even called as class unless you tell mod_perl to use method handlers, which you haven't done here. In the examples in the docs, someone subclasses Apache::Request and then instantiates an object like this:
      my $apr = My::Apache::Request::Subclass->new($r);
      That is not what happens when mod_perl calls your handler. It doesn't call new, since new() is not a special method in Perl. It calls handler (well, you could tell it to call something else, but it's not important), passing an Apache::request object (note the lowercase r) as the only parameter. This object is normally referred to as $r, and it's the same thing you get by calling Apache->request().

      At this point, you can create an Apache::Request object by passing $r to Apache::Request->new(), or instantiate a subclass of Apache::Request in the same way. You can even make it so that other people will get your subclass object when they call Apache->request() by calling it as a set method:

      Apache->request($apr);
      However, there is almost never a good reason to subclass Apache::Request and I don't understand why you think this will help with your session management woes. Apache::Request has nothing to do with session management. It only exists for the current request and nothing in it is saved when it goes away. So, please explain what you are really trying to do, and maybe I can suggest a better solution.

        I think the problem I was having was my understanding of exactly how mod_perl works. I've been operating under the assumption that I was getting an Apache::Request object when this, clearly, is not the case. Up until now, the distinction hasn't mattered, as I've been able to just treat the reference passed into the handler as an "object" and everything is fine.

        What I'm running into now is trying to organize the ball of mud that the application has become. We have a set of application handlers that the actual Apache handler calls based some URI formatting rules. For example, the URI www.example.com/Foo/bar will instantiate a copy of a Foo object, call the bar method and pass the resulting values back to an instance of the Template Toolkit for display.

        The problem comes into being when that object needs to forward calls to successive methods. For example, say the bar method needs to do some input validation and store the validated input for passing into the baz method.

        We have no consistent methodology for doing this at the moment, other than the requirement that the tied hash of an Apache::Session object is passed into every method. We have some objects that will put the data they need into a named hashref underneath the session like so:

        $SESSION->{Foo} = { Value => 94, name => 'Frank' }
        While others will do the following:
        $SESSION->{value} = 94; $SESSION->{name} = 'Frank';
        Where I run into bigger problems is when code uses a key like "validate". Some of the authentication code uses "validate" to insure that the user is logged in, while other functions set a "validate" key to mean that the variables have been validated. We have masses of special case if statements throughout the application to move these "magic" tokens around so we don't break other functionality. Obviously, it's a nasty situation that needs to be refactored.

        My thinking was that I could subclass Apache::Request, place my session handling code within the subclass, and add a couple of methods to do things like add an application global setting, and a couple of helper functions for adding the object specialized stuff, above. Perhaps something like this:

        # Set a global "login" variable $r->set_global( Login => 1 ); # Do some other stuff, then let the Bar function do things. $r->private_variable( Package => "Foo", Function => "Bar", Value => "S +ome Value" );
        This needs a bit more refinement, obviously, but I think it would solve some of our problems.

        I'm imagining a set of functions that are easy to work with and make accessing values stored between requests logical instead of the chaotic approach that the application currently uses.

        Is that a better explaination?

      How do I get the server to return my new object instead of a generic Apache object. Or, how do I get the server to return my object blessed as an Apache object, instead of returning a generic Apache::Request object?

      I think the short answer is, you can't/don't. No matter how hard you try, handler() will always receive a vanilla Apache object

      So the next best thing would be to always start out your handlers like so:

      sub handler { my $r = shift; my $my_r = My::Apache::Request->new($r); # do interesting things with $my_r }

      Or perhaps you can create something like the Apache->instance() method, and do something like:

      # somewhere in your code... my $r = My::Apache::Request->instance; # in My::Apache::Request; package My::Apache::Request; use base qw(Apache::Singleton); # or something like it sub _new_instance { my $class = shift; return $class->new(r => Apache::Request->instance); }

        I'm thinking of mod_perl as a set of Perl objects to help you deal with passing stuff around an Apache application. My thinking is wrong, but it hasn't mattered until now.

        I've spent the last several years dealing with mod_perl on a daily basis, yet haven't hit a point yet where I've needed to know more about the internals than the simple cook-book recipies and how to set up a Mason handler that deals with virtual hosts nicely.

        What I'm really noticing now is a lack of documentation for mid-level mod_perl stuff. The things I'm trying to do seem a little more advanced than general mod_perl stuff, but nothing that should require delving into the C and XS code. All of my searching has come up with stuff that's either geared more towards getting started with mod_perl or turning around and doing actual tweaking of the mod_perl engine itself.

        Thanks for the help on this, by the way. It's been most illuminating.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://381849]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (7)
As of 2024-04-23 10:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found