  | 
 
 
 
 |  
 |  | 
 
  
    | MasonX::WebApp(3) | 
    User Contributed Perl Documentation | 
    MasonX::WebApp(3) | 
   
 
MasonX::WebApp - Works with Mason to do processing before Mason is
    invoked 
  # Create a subclass of MasonX::WebApp
  package My::WebApp;
  use base 'MasonX::WebApp';
  sub _init
  {
      # do something interesting, like making sure all incoming
      # arguments are UTF-8
  }
  # Create a handler() for it
  package My::MasonHandler;
  my $ah = MasonX::WebApp::ApacheHandler->new( ... );
  sub handler
  {
      # see docs for details
  }
  # In your Apache config file
  <Location />
    SetHandler   perl-script
    PerlHandler  My::MasonHandler
  </Location>
"MasonX::WebApp" works with
    Mason to let you do processing before Mason is ever invoked. There
    are a number of things that one might want to do: 
  - Argument munging
    
You might want to make sure all incoming arguments are UTF-8
        encoded. Or you might want to create some objects which Mason will see
        as incoming arguments. For example, a "user_id" parameter
        could be turned into a user object. 
   
  - Handle requests without Mason
    
If you're not generating output for the browser other than a
        redirect, then there's no reason to use Mason. You can use a
        "MasonX::WebApp" subclass to handle
        all form submissions, for example. 
    This has the added benefit of making it easier to preload this
        code once during server startup. 
   
  - Authorization checks
    
Why do authorization checks in Mason if a failed check just
        leads to a redirect or NOT FOUND return code? 
   
 
To use "MasonX::WebApp", you
    should create a "MasonX::WebApp" subclass.
    By itself, "MasonX::WebApp" won't do a
    whole lot for you, but it provides a nice framework for building on. 
"MasonX::WebApp", out of the
    box, provides the following: 
  - Session creation
    
You can declare your session parameters, and
        "MasonX::WebApp" will create an
        "Apache::Session::Wrapper" object for
        you, available via the session() method.
        Alternately, you can implement your own session creation method in your
        subclass. 
   
  - Argument munging
    
The arguments which will eventually be passed to Mason are
        available via the args() method. This method
        returns a hashref, and any changes made to this reference will affect
        the arguments eventually passed to Mason. 
   
  - "Actions"
    
"MasonX::WebApp" will call
        appropriate methods based on the URI. These methods are determined by
        removing a prefix from the URI (settable via a class method), and then
        using the remainder as a method name to be called on the webapp
      object. 
   
  - Generate output without using Mason
    
If you want to generate output that doesn't really need, like
        sending a PDF file for download, you can do that with your webapp object
        before Mason is invoked. 
   
  - Messages, errors, and "saved arguments"
    
If you are using sessions, the webapp object provides methods
        to store regular messages, error messages, and save arguments (to
        re-populate a form, for example) in the session. It also provides
        methods to retrieve these. 
   
  - Convenient uri creation
    
The uri() method provides a nice
        flexible API for creating URIs. 
   
 
You can set some parameters for your subclass declaratively, by
    calling class methods. These methods store data using
    "Class::Data::Inheritable", so you can
    inherit from your subclasses and inherit these parameters. 
The following class methods are offered for declaring
  parameters: 
  - ActionURIPrefix
    
This is the prefix used to determine which, if any,
        "action" method should be called on the webapp object. By
        default, this is /submit/. So if a request comes in for
        /submit/login, then the login() method
        will be called. 
    If you change this, your prefix must also start and with a
        slash (/). 
    Setting this will override a previous setting of
        "ActionURIPrefixRegex", so do not set
        both of these parameters in your subclass. 
   
  - ActionURIPrefixRegex
    
If you want to do something more complex than specifying one
        prefix, you can use this method to specify a regex which determines if a
        URI is calling an action. For example, you might want to allow both
        /submit/ and /download/ as prefixes: 
    
      $self->ActionURIPrefixRegex( qr{^/(?:submit|download)/} );
    
   
  - ApacheHandlerParams
    
This should be a hash reference of options that will be passed
        to the "MasonX::WebApp::ApacheHandler"
        class's new() method when creating a new
        ApacheHandler object. You don't need to set this if you are creating the
        ApacheHandler from scratch in your subclass, and/or if you are providing
        your own mod_perl handler()
      subroutine/method. 
    The default handler() will create a
        new "MasonX::WebApp::ApacheHandler"
        object on every request, using these parameters. 
   
  - MasonGlobalName
    
The variable name to use for the webapp object in Mason
        components. The default handler() sets this
        global. 
    The default value for this is
      $WebApp. 
   
  - RequireAbortAfterAction
    
If this is true, then an exception will be thrown if an action
        is handled but no abort is generated inside the action method. A
        redirect is a form of abort. 
    This defaults to true. 
   
  - SessionWrapperParams
    
A hash reference of parameters to be passed to the
        "Apache::Session::Wrapper" class's
        new() method. 
    You don't need to set this if you are creating your own
        session wrapper object. 
    Setting this also causes
        "UseSession" to be set to a true
        value. 
   
  - UseSession
    
Set this to true if you are creating your own session wrapper
        object, so that "MasonX::WebApp" knows
        it can call session() internally. 
   
 
Some methods throw exceptions. Exceptions classes are created
    using "Exception::Class". 
The folowing methods are public, and can be called from subclasses
    or from elsewhere, like in Mason components. 
  - •
 
  - new()
    
This is the constructor method. It expects to receive at least
        two arguments: 
   
 
  - apache_req
    
An Apache request object, which must be an
        "Apache" object or a subclass's
        object. 
   
  - args
    
A hash reference of arguments. If you are using the
        "MasonX::WebApp::ApacheHandler" class,
        you can use the return value of its
        request_args() method. 
   
 
 
The new method will do the following: 
Call _set_session() if
    UseSession() is true. 
Call _init(). If additional arguments are
    given then they will be passed along to your _init()
    method, if you have one. The call to _init() is
    wrapped in an eval block. If an exception is thrown, and that exception is
    not a
    "MasonX::WebApp::Exception::Redirect"
    exception, then it will be rethrown. Redirect exceptions are not
    rethrown. 
Call _handle_action(). 
Return the newly created webapp object. 
 
  - apache_req()
    
Returns the Apache request given to the
        new() method. 
   
  - args()
    
Returns a hash reference containing the arguments passed to
        the new() method. Since this is the same
        reference as is stored in the
        "MasonX::WebApp::ApacheHandler"
        object, any changes to this reference will be visible to Mason
        components. 
   
  - session_wrapper()
    
Returns the
        "Apache::Session::Wrapper" object for
        the webapp object. 
    If UseSession() is not true, calling
        this method throws an exception. 
   
  - session()
    
A shortcut for calling
        "$webapp->session_wrapper->session". 
    If UseSession() is not true, calling
        this method throws an exception. 
   
  - redirect()
    
This method can take a number of named parameters. If it is
        given a "uri" parameter, then it uses this URI for the
        redirection. Otherwise, it takes any parameters it is given and calls
        the uri() method with them. When it calls
        uri(), it sets the "xhtml" parameter
        to false, so you do not need to do this. 
    If called inside the context of a Mason request, it calls
        redirect() on the Mason request object. 
    Otherwise it sets the value of
        aborted() to true, sends a redirect using the
        apache request object, and then throws a
        "MasonX::WebApp::Exception::Aborted"
        exception. 
   
  - abort( $status )
    
Stops processing by throwing a
        "MasonX::WebApp::Exception::Aborted"
        exception. You can pass a status code (from
        "Apache::Constants") as an optional
        argument. If nothing is given then this will default to
        "OK". This status code will be
        available via the status_code() method. 
    You will need to use this method if you generate your own
        output in an action handling method and don't want to pass control to
        Mason afterwards. 
   
  - aborted()
    
Returns a boolean value indicating whether or not
        abort() has been called on the webapp object.
        This will be true if the redirect() method was
        called, since it uses abort(). 
   
  - abort_status()
    
The value passed to the abort()
        method. If no value was passed, this will the
        "OK" constant from
        "Apache::Constants". 
   
  - uri()
    
This creates a URI string based on the parameters it receives.
        It accepts the following parameters: 
   
 
  - path
    
The path portion of the URI. This is the only required
        parameter. 
   
  - query
    
A hash reference which will be turned into a query string. The
        keys of the hash reference may point to scalars, array references, or
        hash references. Hash reference values are treated the same way as array
        references. 
   
  - fragment
    
Optional 
   
  - host
    
Optional. By default, URIs are relative, and this is not
      used. 
   
  - port
    
Optional. This is ignored unless "host" is also
        passed. 
   
  - scheme
    
Defaults to "http", but since URIs are relative by
        default, this is ignored unless "host" is also passed. 
   
  - username
 
  - password
    
Optional. These are both ignored unless "host" is
        also passed. If "password" is passed without a
        "username", it is ignored. 
   
  - xhtml
    
Defaults to true. If this is true, then the returned URI will
        have any ampersands (&) in the query string HTML-escaped
        (&). 
   
 
 
  - messages()
    
Returns an array of non-error messages stored in the session.
        This method is destructive, as calling it removes the messages
        from the session. 
    If you are not using sessions, calling this method throws an
        exception. 
   
  - errors()
    
Returns an array of error messages stored in the session. This
        method is destructive, as calling it removes the error messages
        from the session. 
    If you are not using sessions, calling this method throws an
        exception. 
   
  - saved_args()
    
Returns a hash reference of arguments saved in the session.
        This method is not destructive. If you are saving arguments in
        the session, you should probably make sure that
        clean_session() is called at the end of every
        request. The default handler() sub does
      this. 
    If you are not using sessions, calling this method throws an
        exception. 
   
  - clean_session()
    
Removes any messages, error messages, and saved args stored in
        the session. This should be called a the end of each request in order to
        prevent these value leaking over into the next request. 
    If you are not using sessions, calling this method throws an
        exception. 
   
 
These methods are intended to be called directly or overridden by
    your subclass. 
  - _LoadActions()
    
If you want to define actions in other files, like
        "My::WebApp::User", this method
        provides a handy way to load all of them at once. It looks for modules
        under your subclass's package name and loads them. So if your subclass
        is in the package "My::WebApp", then
        it looks for modules matching
        "My::WebApp::*". 
    Note that because
        "MasonX::WebApp" will call action
        methods on $self, all of these modules must set
        the package to the same thing. In the example, above, all of the action
        modules would need to set their package to
        "My::WebApp". 
    You can always override
        _handle_action() to implement your own action
        dispaching if you dislike this restriction. 
   
  - _init()
    
Called from the new() method. By
        default this does nothing, but you can override it to do something
        interesting with the newly created object. 
   
  - _is_valid_action()
    
This method takes an action name and returns a boolean value
        indicating whether or not the action is valid. By default, this simply
        checks if "$self->can($action)",
        but you should consider overriding this to restrict what methods can be
        called via a URI. 
   
  - _make_session_wrapper()
    
This method is called during object construction if
        "UseSession" is true. By default, it
        creates a new
        "Apache::Session::Wrapper" object with
        the parameters from
        "SessionWrapperParams". You can
        override this method to provide your own session wrapper creation. 
   
  - _handle_action()
    
This method is called during object construction. If a
        redirect was done earlier in the object creation process, then it does
        nothing. Otherwise, it looks at the requested URI to see if it matches
        the "ActionURIPrefix". If it does, it
        turns the URI into a method name by stripping off the prefix, and it
        calls that method on the webapp object. 
    You can override this to provide your own dispatching system
        for requests. 
    Note that this method should not call out to Mason. It
        should only be used for actions that don't need Mason. 
   
  - _save_arg()
    
Given a key and value, this method saves them in the session
        so that they will be available via the
        saved_args() method. 
    If UseSession() is not true, calling
        this method throws an exception. 
   
  - _add_message()
    
Given a string, this method stores that string in the session
        so that it is available via the messages()
        method. 
    If UseSession() is not true, calling
        this method throws an exception. 
   
  - _add_error_message()
    
Given a string, this method stores that string in the session
        so that it is available via the errors()
      method. 
    If UseSession() is not true, calling
        this method throws an exception. 
   
  - _handle_error()
    
This method can be used to handle exceptions that occur during
        actions. 
    It provides a quick way to store error messages and arguments
        in the session, and then issue a redirect. 
    It takes several parameters: 
   
 
  - error
    
This should be either a scalar, an array reference or an
        object. If it is a scalar, this is assumed to be an error message. If it
        an array reference, it is assumed to be an array reference of scalars,
        each of which contains a single message. 
    If an object is given, then it first looks for a
        messages() method in that object. This method
        should return an array of scalars, each of which represents an error
        message. 
    Otherwise it looks for a method called
        message(), which should return a single
      scalar. 
    It adds each error message to the session via the
        _add_error_message() method. 
   
  - save_args
    
This is a hash reference of arguments that should be saved in
        the session. Each key/value pair will be saved by calling the the
        _save_arg() method. 
   
 
 
All other arguments are passed along to the
    redirect() method. 
If UseSession() is not true, calling this
    method throws an exception. 
 
  - •
 
  - _apache_handler_object()
    
This method is called in the default
        handler() method in order to create a new
        "MasonX::WebApp::ApacheHandler"
        object. It simply calls that class's new()
        method with the parameters set via
        "ApacheHandlerParams". 
   
 
In order to avoid stepping on your toes, all hash keys in the
    webapp object, and all keys that it creates in the session object, are of
    the form "__blahblah__". In other words, they always start and end
    with two underscores (__). This should make it easy to avoid name conflicts
    when subclassing this module or when using the session it provides. 
The "MasonX::WebApp" class
    provides a default handler method. 
I would recommend that instead of using this method, you create
    your own mod_perl handler that does something similar, because the default
    is not very efficient, given that it creates a new
    "MasonX::WebApp::ApacheHandler" object for
    each request. It is provided primarily as a reference implementation, and so
    that others can experiment with this webapp code quickly. 
When creating your own handler, it might be useful to copy the one
    in this module as a reference. 
In your own handler, there are several important guidelines you
    should follow. 
  - First of all, your handler() should use the
      "MasonX::WebApp::ApacheHandler" class
      for the ApacheHandler object, not
      "HTML::Mason::ApacheHandler". The MasonX
      subclass caches the value of request_args(). This
      is done so that these arguments can be passed to the
      "MasonX::WebApp" constructor and still
      be made available to Mason. It also makes sure that Mason's arguments are
      the same hash reference as is available from the
      args() method. This is very important if you want
      to do any argument munging in your subclass. Also, since mod_perl will
      only read POSTed data once, without this caching Mason would not see any
      arguments at all!
 
  - Get the request arguments by calling
      request_args() on the ApacheHandler object,
      passing an "Apache" object as the
      method's argument. Unless you set the ApacheHandler's
      "args_method" parameter to
      "CGI", you must pass in an
      "ApacheRequest" object.
    
You will need to pass the hash reference returned by this
        method to the constructor for your WebApp object. 
   
  - After creating a new webapp object, make sure to check the value of the
      aborted() method for that object. If it is true,
      you should return the status code given by the
      abort_status() method from your
      handler(). Remember, this will default to
      "OK" if no status was given to the
      abort() method.
 
  - If you are using the message, error message, or saved arg features, you
      should make sure that clean_session() is called at
      the end of every request. This means that you need to wrap the call to the
      ApacheHandler's handle_request() method in an eval
      block, as in the default handler()
 
  - If you use the set_global() method to make the
      webapp object available to your components, and your ApacheHandler
      objects persist across requests, then you need to call
      set_global() again after the request is handled,
      and this time set that global to undef. This ensures that the webapp
      object will be destroyed.
    
A safer alternative, if you know what class your components
        will be compiled in, is to do this: 
    
     local $HTML::Mason::Commands::App = $app;
    
    The use of "local" ensures
        that $app will go out of scope at the end of
        handler() subroutine. 
   
 
You can, of course, do anything you want in your own
    handler() method. I often create an
    "Apache::Request" object with a
    "POST_MAX" parameter, in order to prevent a DoS from a
    ridiculously large POST. 
I also often handle errors without dying, and instead will log
    them and present a more friendly page to the user. If you want to do this,
    keep in mind that constructing a webapp object can throw exceptions, so you
    may want to trap these in an "eval"
  block. 
If you do something cool with this code, write about it on the
    Mason HQ site, masonhq.com (which is a big wiki), or send a post to the
    Mason users list. 
Example handler() 
Here is an example of an alternate handler(). This one is
    written as a function, not a method. 
  package My::MasonHandler;
  sub handler
  {
      my $apr = Apache::Request->new(shift);
      my $args = $ah->request_args($apr);
      my $app = $class->new( apache_req => $apr, args => $args );
      return $app->abort_status if $app->aborted;
      local $My::ComponentPackage::WebApp = $app;
      my $return = eval { $ah->handle_request($r) };
      my $err = $@;
      $app->clean_session if $class->UseSession;
      die $err if $err;
      return $return;
   }
Then in your Apache configuration, you would use this handler: 
  <Location />
    SetHandler   perl-script
    PerlHandler  My::MasonHandler
  </Location>
If you like the basic idea of this code (run things before a Mason
    component is invoked), but you don't want to create a subclass, I encourage
    you to take a look at David Wheeler's
    "MasonX::Interp::WithCallbacks" module. In
    fact, I encourage you to take a look at it anyway, since it may be more
    appropriate than this one, depending on your needs. 
Bug reports and requests for help should be sent to the
    mason-users list. See http://www.masonhq.com/resources/mailing_lists.html
    for more details. 
Dave Rolsky, <autarch@urth.org> 
This program is free software; you can redistribute it and/or
    modify it under the same terms as Perl itself. 
The full text of the license can be found in the LICENSE file
    included with this module. 
 
 
  Visit the GSP FreeBSD Man Page Interface. Output converted with ManDoc.
  |