.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32 .\" .\" Standard preamble: .\" ======================================================================== .de Sh \" Subsection heading .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. | will give a .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' .\" expand to `' in nroff, nothing in troff, for use with C<>. .tr \(*W-|\(bv\*(Tr .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .\" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .hy 0 .if n .na .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MasonX::WebApp 3" .TH MasonX::WebApp 3 "2008-01-18" "perl v5.8.8" "User Contributed Perl Documentation" .SH "NAME" MasonX::WebApp \- Works with Mason to do processing before Mason is invoked .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& # Create a subclass of MasonX::WebApp \& package My::WebApp; .Ve .PP .Vb 1 \& use base 'MasonX::WebApp'; .Ve .PP .Vb 5 \& sub _init \& { \& # do something interesting, like making sure all incoming \& # arguments are UTF-8 \& } .Ve .PP .Vb 1 \& # Create a handler() for it .Ve .PP .Vb 1 \& package My::MasonHandler; .Ve .PP .Vb 1 \& my $ah = MasonX::WebApp::ApacheHandler->new( ... ); .Ve .PP .Vb 4 \& sub handler \& { \& # see docs for details \& } .Ve .PP .Vb 1 \& # In your Apache config file .Ve .PP .Vb 4 \& \& SetHandler perl-script \& PerlHandler My::MasonHandler \& .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\f(CW\*(C`MasonX::WebApp\*(C'\fR works with Mason to let you do processing \fIbefore\fR Mason is ever invoked. There are a number of things that one might want to do: .IP "* Argument munging" 4 .IX Item "Argument munging" You might want to make sure all incoming arguments are \s-1UTF\-8\s0 encoded. Or you might want to create some objects which Mason will see as incoming arguments. For example, a \*(L"user_id\*(R" parameter could be turned into a user object. .IP "* Handle requests without Mason" 4 .IX Item "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 \f(CW\*(C`MasonX::WebApp\*(C'\fR subclass to handle all form submissions, for example. .Sp This has the added benefit of making it easier to preload this code once during server startup. .IP "* Authorization checks" 4 .IX Item "Authorization checks" Why do authorization checks in Mason if a failed check just leads to a redirect or \s-1NOT\s0 \s-1FOUND\s0 return code? .SH "USAGE" .IX Header "USAGE" To use \f(CW\*(C`MasonX::WebApp\*(C'\fR, you should create a \f(CW\*(C`MasonX::WebApp\*(C'\fR subclass. By itself, \f(CW\*(C`MasonX::WebApp\*(C'\fR won't do a whole lot for you, but it provides a nice framework for building on. .Sh "What MasonX::WebApp Provides" .IX Subsection "What MasonX::WebApp Provides" \&\f(CW\*(C`MasonX::WebApp\*(C'\fR, out of the box, provides the following: .IP "* Session creation" 4 .IX Item "Session creation" You can declare your session parameters, and \f(CW\*(C`MasonX::WebApp\*(C'\fR will create an \f(CW\*(C`Apache::Session::Wrapper\*(C'\fR object for you, available via the \f(CW\*(C`session()\*(C'\fR method. Alternately, you can implement your own session creation method in your subclass. .IP "* Argument munging" 4 .IX Item "Argument munging" The arguments which will eventually be passed to Mason are available via the \f(CW\*(C`args()\*(C'\fR method. This method returns a hashref, and any changes made to this reference will affect the arguments eventually passed to Mason. .ie n .IP "* ""Actions""" 4 .el .IP "* ``Actions''" 4 .IX Item "Actions" \&\f(CW\*(C`MasonX::WebApp\*(C'\fR will call appropriate methods based on the \s-1URI\s0. These methods are determined by removing a prefix from the \s-1URI\s0 (settable via a class method), and then using the remainder as a method name to be called on the webapp object. .IP "* Generate output without using Mason" 4 .IX Item "Generate output without using Mason" If you want to generate output that doesn't really need, like sending a \s-1PDF\s0 file for download, you can do that with your webapp object before Mason is invoked. .ie n .IP "* Messages, errors, and ""saved arguments""" 4 .el .IP "* Messages, errors, and ``saved arguments''" 4 .IX Item "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. .IP "* Convenient uri creation" 4 .IX Item "Convenient uri creation" The \f(CW\*(C`uri()\*(C'\fR method provides a nice flexible \s-1API\s0 for creating URIs. .PP You can set some parameters for your subclass declaratively, by calling class methods. These methods store data using \&\f(CW\*(C`Class::Data::Inheritable\*(C'\fR, so you can inherit from your subclasses and inherit these parameters. .Sh "Declarative Parameters" .IX Subsection "Declarative Parameters" The following class methods are offered for declaring parameters: .IP "* ActionURIPrefix" 4 .IX Item "ActionURIPrefix" This is the prefix used to determine which, if any, \*(L"action\*(R" method should be called on the webapp object. By default, this is \&\fI/submit/\fR. So if a request comes in for \fI/submit/login\fR, then the \&\f(CW\*(C`login()\*(C'\fR method will be called. .Sp If you change this, your prefix must also start and with a slash (/). .Sp Setting this will override a previous setting of \&\f(CW\*(C`ActionURIPrefixRegex\*(C'\fR, so do not set both of these parameters in your subclass. .IP "* ActionURIPrefixRegex" 4 .IX Item "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 \s-1URI\s0 is calling an action. For example, you might want to allow both \&\fI/submit/\fR and \fI/download/\fR as prefixes: .Sp .Vb 1 \& $self->ActionURIPrefixRegex( qr{^/(?:submit|download)/} ); .Ve .IP "* ApacheHandlerParams" 4 .IX Item "ApacheHandlerParams" This should be a hash reference of options that will be passed to the \&\f(CW\*(C`MasonX::WebApp::ApacheHandler\*(C'\fR class's \f(CW\*(C`new()\*(C'\fR 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 \f(CW\*(C`handler()\*(C'\fR subroutine/method. .Sp The default \f(CW\*(C`handler()\*(C'\fR will create a new \&\f(CW\*(C`MasonX::WebApp::ApacheHandler\*(C'\fR object on every request, using these parameters. .IP "* MasonGlobalName" 4 .IX Item "MasonGlobalName" The variable name to use for the webapp object in Mason components. The default \f(CW\*(C`handler()\*(C'\fR sets this global. .Sp The default value for this is \f(CW$WebApp\fR. .IP "* RequireAbortAfterAction" 4 .IX Item "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. .Sp This defaults to true. .IP "* SessionWrapperParams" 4 .IX Item "SessionWrapperParams" A hash reference of parameters to be passed to the \&\f(CW\*(C`Apache::Session::Wrapper\*(C'\fR class's \f(CW\*(C`new()\*(C'\fR method. .Sp You don't need to set this if you are creating your own session wrapper object. .Sp Setting this also causes \f(CW\*(C`UseSession\*(C'\fR to be set to a true value. .IP "* UseSession" 4 .IX Item "UseSession" Set this to true if you are creating your own session wrapper object, so that \f(CW\*(C`MasonX::WebApp\*(C'\fR knows it can call \f(CW\*(C`session()\*(C'\fR internally. .Sh "Exceptions" .IX Subsection "Exceptions" Some methods throw exceptions. Exceptions classes are created using \&\f(CW\*(C`Exception::Class\*(C'\fR. .Sh "Public Methods" .IX Subsection "Public Methods" The folowing methods are public, and can be called from subclasses or from elsewhere, like in Mason components. .IP "* \fInew()\fR" 4 .IX Item "new()" This is the constructor method. It expects to receive at least two arguments: .RS 4 .IP "* apache_req" 8 .IX Item "apache_req" An Apache request object, which must be an \f(CW\*(C`Apache\*(C'\fR object or a subclass's object. .IP "* args" 8 .IX Item "args" A hash reference of arguments. If you are using the \&\f(CW\*(C`MasonX::WebApp::ApacheHandler\*(C'\fR class, you can use the return value of its \f(CW\*(C`request_args()\*(C'\fR method. .RE .RS 4 .Sp The new method will do the following: .Sp Call \f(CW\*(C`_set_session()\*(C'\fR if \f(CW\*(C`UseSession()\*(C'\fR is true. .Sp Call \f(CW\*(C`_init()\*(C'\fR. If additional arguments are given then they will be passed along to your \f(CW\*(C`_init()\*(C'\fR method, if you have one. The call to \&\f(CW\*(C`_init()\*(C'\fR is wrapped in an eval block. If an exception is thrown, and that exception is not a \f(CW\*(C`MasonX::WebApp::Exception::Redirect\*(C'\fR exception, then it will be rethrown. Redirect exceptions are \fInot\fR rethrown. .Sp Call \f(CW\*(C`_handle_action()\*(C'\fR. .Sp Return the newly created webapp object. .RE .IP "* \fIapache_req()\fR" 4 .IX Item "apache_req()" Returns the Apache request given to the \f(CW\*(C`new()\*(C'\fR method. .IP "* \fIargs()\fR" 4 .IX Item "args()" Returns a hash reference containing the arguments passed to the \&\f(CW\*(C`new()\*(C'\fR method. Since this is the same reference as is stored in the \&\f(CW\*(C`MasonX::WebApp::ApacheHandler\*(C'\fR object, any changes to this reference will be visible to Mason components. .IP "* \fIsession_wrapper()\fR" 4 .IX Item "session_wrapper()" Returns the \f(CW\*(C`Apache::Session::Wrapper\*(C'\fR object for the webapp object. .Sp If \f(CW\*(C`UseSession()\*(C'\fR is not true, calling this method throws an exception. .IP "* \fIsession()\fR" 4 .IX Item "session()" A shortcut for calling \f(CW\*(C`$webapp\->session_wrapper\->session\*(C'\fR. .Sp If \f(CW\*(C`UseSession()\*(C'\fR is not true, calling this method throws an exception. .IP "* \fIredirect()\fR" 4 .IX Item "redirect()" This method can take a number of named parameters. If it is given a \&\*(L"uri\*(R" parameter, then it uses this \s-1URI\s0 for the redirection. Otherwise, it takes any parameters it is given and calls the \f(CW\*(C`uri()\*(C'\fR method with them. When it calls \f(CW\*(C`uri()\*(C'\fR, it sets the \*(L"xhtml\*(R" parameter to false, so you do not need to do this. .Sp If called inside the context of a Mason request, it calls \&\f(CW\*(C`redirect()\*(C'\fR on the Mason request object. .Sp Otherwise it sets the value of \f(CW\*(C`aborted()\*(C'\fR to true, sends a redirect using the apache request object, and then throws a \&\f(CW\*(C`MasonX::WebApp::Exception::Aborted\*(C'\fR exception. .ie n .IP "* abort( $status )" 4 .el .IP "* abort( \f(CW$status\fR )" 4 .IX Item "abort( $status )" Stops processing by throwing a \f(CW\*(C`MasonX::WebApp::Exception::Aborted\*(C'\fR exception. You can pass a status code (from \f(CW\*(C`Apache::Constants\*(C'\fR) as an optional argument. If nothing is given then this will default to \&\f(CW\*(C`OK\*(C'\fR. This status code will be available via the \f(CW\*(C`status_code()\*(C'\fR method. .Sp 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. .IP "* \fIaborted()\fR" 4 .IX Item "aborted()" Returns a boolean value indicating whether or not \f(CW\*(C`abort()\*(C'\fR has been called on the webapp object. This will be true if the \f(CW\*(C`redirect()\*(C'\fR method was called, since it uses \f(CW\*(C`abort()\*(C'\fR. .IP "* \fIabort_status()\fR" 4 .IX Item "abort_status()" The value passed to the \f(CW\*(C`abort()\*(C'\fR method. If no value was passed, this will the \f(CW\*(C`OK\*(C'\fR constant from \f(CW\*(C`Apache::Constants\*(C'\fR. .IP "* \fIuri()\fR" 4 .IX Item "uri()" This creates a \s-1URI\s0 string based on the parameters it receives. It accepts the following parameters: .RS 4 .IP "* path" 8 .IX Item "path" The path portion of the \s-1URI\s0. This is the only required parameter. .IP "* query" 8 .IX Item "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. .IP "* fragment" 8 .IX Item "fragment" Optional .IP "* host" 8 .IX Item "host" Optional. By default, URIs are relative, and this is not used. .IP "* port" 8 .IX Item "port" Optional. This is ignored unless \*(L"host\*(R" is also passed. .IP "* scheme" 8 .IX Item "scheme" Defaults to \*(L"http\*(R", but since URIs are relative by default, this is ignored unless \*(L"host\*(R" is also passed. .IP "* username" 8 .IX Item "username" .PD 0 .IP "* password" 8 .IX Item "password" .PD Optional. These are both ignored unless \*(L"host\*(R" is also passed. If \&\*(L"password\*(R" is passed without a \*(L"username\*(R", it is ignored. .IP "* xhtml" 8 .IX Item "xhtml" Defaults to true. If this is true, then the returned \s-1URI\s0 will have any ampersands (&) in the query string HTML-escaped (&). .RE .RS 4 .RE .IP "* \fImessages()\fR" 4 .IX Item "messages()" Returns an array of non-error messages stored in the session. This method is \fIdestructive\fR, as calling it removes the messages from the session. .Sp If you are not using sessions, calling this method throws an exception. .IP "* \fIerrors()\fR" 4 .IX Item "errors()" Returns an array of error messages stored in the session. This method is \fIdestructive\fR, as calling it removes the error messages from the session. .Sp If you are not using sessions, calling this method throws an exception. .IP "* \fIsaved_args()\fR" 4 .IX Item "saved_args()" Returns a hash reference of arguments saved in the session. This method is \fInot\fR destructive. If you are saving arguments in the session, you should probably make sure that \f(CW\*(C`clean_session()\*(C'\fR is called at the end of every request. The default \f(CW\*(C`handler()\*(C'\fR sub does this. .Sp If you are not using sessions, calling this method throws an exception. .IP "* \fIclean_session()\fR" 4 .IX Item "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. .Sp If you are not using sessions, calling this method throws an exception. .Sh "Protected Methods" .IX Subsection "Protected Methods" These methods are intended to be called directly or overridden by your subclass. .IP "* \fI_LoadActions()\fR" 4 .IX Item "_LoadActions()" If you want to define actions in other files, like \&\f(CW\*(C`My::WebApp::User\*(C'\fR, 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 \f(CW\*(C`My::WebApp\*(C'\fR, then it looks for modules matching \f(CW\*(C`My::WebApp::*\*(C'\fR. .Sp Note that because \f(CW\*(C`MasonX::WebApp\*(C'\fR will call action methods on \&\f(CW$self\fR, 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 \f(CW\*(C`My::WebApp\*(C'\fR. .Sp You can always override \f(CW\*(C`_handle_action()\*(C'\fR to implement your own action dispaching if you dislike this restriction. .IP "* \fI_init()\fR" 4 .IX Item "_init()" Called from the \f(CW\*(C`new()\*(C'\fR method. By default this does nothing, but you can override it to do something interesting with the newly created object. .IP "* \fI_is_valid_action()\fR" 4 .IX Item "_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 \f(CW\*(C`$self\->can($action)\*(C'\fR, but you should consider overriding this to restrict what methods can be called via a \s-1URI\s0. .IP "* \fI_make_session_wrapper()\fR" 4 .IX Item "_make_session_wrapper()" This method is called during object construction if \f(CW\*(C`UseSession\*(C'\fR is true. By default, it creates a new \f(CW\*(C`Apache::Session::Wrapper\*(C'\fR object with the parameters from \f(CW\*(C`SessionWrapperParams\*(C'\fR. You can override this method to provide your own session wrapper creation. .IP "* \fI_handle_action()\fR" 4 .IX Item "_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 \s-1URI\s0 to see if it matches the \&\f(CW\*(C`ActionURIPrefix\*(C'\fR. If it does, it turns the \s-1URI\s0 into a method name by stripping off the prefix, and it calls that method on the webapp object. .Sp You can override this to provide your own dispatching system for requests. .Sp Note that this method should \fInot\fR call out to Mason. It should only be used for actions that don't need Mason. .IP "* \fI_save_arg()\fR" 4 .IX Item "_save_arg()" Given a key and value, this method saves them in the session so that they will be available via the \f(CW\*(C`saved_args()\*(C'\fR method. .Sp If \f(CW\*(C`UseSession()\*(C'\fR is not true, calling this method throws an exception. .IP "* \fI_add_message()\fR" 4 .IX Item "_add_message()" Given a string, this method stores that string in the session so that it is available via the \f(CW\*(C`messages()\*(C'\fR method. .Sp If \f(CW\*(C`UseSession()\*(C'\fR is not true, calling this method throws an exception. .IP "* \fI_add_error_message()\fR" 4 .IX Item "_add_error_message()" Given a string, this method stores that string in the session so that it is available via the \f(CW\*(C`errors()\*(C'\fR method. .Sp If \f(CW\*(C`UseSession()\*(C'\fR is not true, calling this method throws an exception. .IP "* \fI_handle_error()\fR" 4 .IX Item "_handle_error()" This method can be used to handle exceptions that occur during actions. .Sp It provides a quick way to store error messages and arguments in the session, and then issue a redirect. .Sp It takes several parameters: .RS 4 .IP "* error" 8 .IX Item "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. .Sp If an object is given, then it first looks for a \f(CW\*(C`messages()\*(C'\fR method in that object. This method should return an array of scalars, each of which represents an error message. .Sp Otherwise it looks for a method called \f(CW\*(C`message()\*(C'\fR, which should return a single scalar. .Sp It adds each error message to the session via the \&\f(CW\*(C`_add_error_message()\*(C'\fR method. .IP "* save_args" 8 .IX Item "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 \&\f(CW\*(C`_save_arg()\*(C'\fR method. .RE .RS 4 .Sp All other arguments are passed along to the \f(CW\*(C`redirect()\*(C'\fR method. .Sp If \f(CW\*(C`UseSession()\*(C'\fR is not true, calling this method throws an exception. .RE .IP "* \fI_apache_handler_object()\fR" 4 .IX Item "_apache_handler_object()" This method is called in the default \f(CW\*(C`handler()\*(C'\fR method in order to create a new \f(CW\*(C`MasonX::WebApp::ApacheHandler\*(C'\fR object. It simply calls that class's \f(CW\*(C`new()\*(C'\fR method with the parameters set via \&\f(CW\*(C`ApacheHandlerParams\*(C'\fR. .Sh "Hash Keys in the WebApp and Session Objects" .IX Subsection "Hash Keys in the WebApp and Session Objects" 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 \*(L"_\|_blahblah_\|_\*(R". 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. .Sh "The Default \fIhandler()\fP Method" .IX Subsection "The Default handler() Method" The \f(CW\*(C`MasonX::WebApp\*(C'\fR class provides a default handler method. .PP 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 \&\f(CW\*(C`MasonX::WebApp::ApacheHandler\*(C'\fR object for each request. It is provided primarily as a reference implementation, and so that others can experiment with this webapp code quickly. .PP When creating your own handler, it might be useful to copy the one in this module as a reference. .PP In your own handler, there are several important guidelines you should follow. .IP "\(bu" 4 First of all, your \f(CW\*(C`handler()\*(C'\fR should use the \&\f(CW\*(C`MasonX::WebApp::ApacheHandler\*(C'\fR class for the ApacheHandler object, not \f(CW\*(C`HTML::Mason::ApacheHandler\*(C'\fR. The MasonX subclass caches the value of \f(CW\*(C`request_args()\*(C'\fR. This is done so that these arguments can be passed to the \f(CW\*(C`MasonX::WebApp\*(C'\fR constructor and still be made available to Mason. It also makes sure that Mason's arguments are the \&\fIsame\fR hash reference as is available from the \f(CW\*(C`args()\*(C'\fR 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! .IP "\(bu" 4 Get the request arguments by calling \f(CW\*(C`request_args()\*(C'\fR on the ApacheHandler object, passing an \f(CW\*(C`Apache\*(C'\fR object as the method's argument. Unless you set the ApacheHandler's \f(CW\*(C`args_method\*(C'\fR parameter to \*(L"\s-1CGI\s0\*(R", you must pass in an \f(CW\*(C`ApacheRequest\*(C'\fR object. .Sp You will need to pass the hash reference returned by this method to the constructor for your WebApp object. .IP "\(bu" 4 After creating a new webapp object, make sure to check the value of the \f(CW\*(C`aborted()\*(C'\fR method for that object. If it is true, you should return the status code given by the \f(CW\*(C`abort_status()\*(C'\fR method from your \&\f(CW\*(C`handler()\*(C'\fR. Remember, this will default to \f(CW\*(C`OK\*(C'\fR if no status was given to the \f(CW\*(C`abort()\*(C'\fR method. .IP "\(bu" 4 If you are using the message, error message, or saved arg features, you should make sure that \f(CW\*(C`clean_session()\*(C'\fR is called at the end of every request. This means that you need to wrap the call to the ApacheHandler's \f(CW\*(C`handle_request()\*(C'\fR method in an eval block, as in the default \f(CW\*(C`handler()\*(C'\fR .IP "\(bu" 4 If you use the \f(CW\*(C`set_global()\*(C'\fR method to make the webapp object available to your components, \fBand\fR your ApacheHandler objects persist across requests, then you need to call \f(CW\*(C`set_global()\*(C'\fR again after the request is handled, and this time set that global to undef. This ensures that the webapp object will be destroyed. .Sp A safer alternative, if you know what class your components will be compiled in, is to do this: .Sp .Vb 1 \& local $HTML::Mason::Commands::App = $app; .Ve .Sp The use of \f(CW\*(C`local\*(C'\fR ensures that \f(CW$app\fR will go out of scope at the end of \f(CW\*(C`handler()\*(C'\fR subroutine. .PP You can, of course, do anything you want in your own \f(CW\*(C`handler()\*(C'\fR method. I often create an \f(CW\*(C`Apache::Request\*(C'\fR object with a \*(L"\s-1POST_MAX\s0\*(R" parameter, in order to prevent a DoS from a ridiculously large \s-1POST\s0. .PP 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 \f(CW\*(C`eval\*(C'\fR block. .PP If you do something cool with this code, write about it on the Mason \&\s-1HQ\s0 site, masonhq.com (which is a big wiki), or send a post to the Mason users list. .PP \fIExample \fIhandler()\fI\fR .IX Subsection "Example handler()" .PP Here is an example of an alternate \fIhandler()\fR. This one is written as a function, not a method. .PP .Vb 1 \& package My::MasonHandler; .Ve .PP .Vb 3 \& sub handler \& { \& my $apr = Apache::Request->new(shift); .Ve .PP .Vb 1 \& my $args = $ah->request_args($apr); .Ve .PP .Vb 1 \& my $app = $class->new( apache_req => $apr, args => $args ); .Ve .PP .Vb 1 \& return $app->abort_status if $app->aborted; .Ve .PP .Vb 1 \& local $My::ComponentPackage::WebApp = $app; .Ve .PP .Vb 1 \& my $return = eval { $ah->handle_request($r) }; .Ve .PP .Vb 1 \& my $err = $@; .Ve .PP .Vb 1 \& $app->clean_session if $class->UseSession; .Ve .PP .Vb 1 \& die $err if $err; .Ve .PP .Vb 2 \& return $return; \& } .Ve .PP Then in your Apache configuration, you would use this handler: .PP .Vb 4 \& \& SetHandler perl-script \& PerlHandler My::MasonHandler \& .Ve .SH "SEE ALSO" .IX Header "SEE ALSO" 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 \&\f(CW\*(C`MasonX::Interp::WithCallbacks\*(C'\fR 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. .SH "SUPPORT" .IX Header "SUPPORT" 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. .SH "AUTHOR" .IX Header "AUTHOR" Dave Rolsky, .SH "COPYRIGHT" .IX Header "COPYRIGHT" This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .PP The full text of the license can be found in the \s-1LICENSE\s0 file included with this module.