File Coverage

blib/lib/Mason/Request.pm
Criterion Covered Total %
statement 334 345 96.8
branch 39 48 81.2
condition 9 15 60.0
subroutine 104 108 96.3
pod n/a
total 486 516 94.1


line stmt bran cond sub pod time code
1             package Mason::Request;
2             $Mason::Request::VERSION = '2.23';
3 20     20   100 use Carp;
  20         32  
  20         1577  
4 20     20   110 use File::Basename;
  20         24  
  20         1185  
5 20     20   101 use Guard;
  20         36  
  20         888  
6 20     20   10914 use Log::Any qw($log);
  20         34209  
  20         78  
7 20     20   8368 use Mason::Exceptions;
  20         46  
  20         567  
8 20     20   6793 use Mason::TieHandle;
  20         41  
  20         525  
9 20     20   6651 use Mason::Types;
  20         62  
  20         939  
10 20     20   161 use Mason::Moose;
  20         31  
  20         159  
11 20     20   33539 use Scalar::Util qw(blessed reftype weaken);
  20         43  
  20         1446  
12 20     20   109 use Try::Tiny;
  20         28  
  20         5557  
13              
14             my $default_out = sub { my ( $text, $self ) = @_; $self->result->_append_output($text) };
15             my $next_id = 0;
16              
17             # Passed attributes
18             #
19             has 'interp' => ( required => 1, weak_ref => 1 );
20             has 'out_method' => ( isa => 'Mason::Types::OutMethod', default => sub { $default_out }, coerce => 1 );
21              
22             # Derived attributes
23             #
24             has 'buffer_stack' => ( init_arg => undef, default => sub { [] } );
25             has 'declined' => ( init_arg => undef, is => 'rw' );
26             has 'declined_paths' => ( default => sub { {} } );
27             has 'go_result' => ( init_arg => undef );
28             has 'id' => ( init_arg => undef, default => sub { $next_id++ } );
29             has 'output' => ( init_arg => undef, default => '' );
30             has 'page' => ( init_arg => undef );
31             has 'path_info' => ( init_arg => undef, default => '' );
32             has 'request_args' => ( init_arg => undef );
33             has 'request_code_cache' => ( init_arg => undef, default => sub { {} } );
34             has 'request_path' => ( init_arg => undef );
35             has 'result' => ( init_arg => undef, lazy_build => 1 );
36             has 'run_params' => ( init_arg => undef );
37              
38             # Globals, localized to each request
39             #
40             our ( $current_request, $current_buffer );
41 20     20   7116 method current_request () { $current_request }
  0     0   0  
  0         0  
  0         0  
42              
43             #
44             # BUILD
45             #
46              
47 20     20   6564 method BUILD ($params) {
  185     185   397  
  185         363  
  185         243  
48              
49             # Make a copy of params sans interp
50             #
51 185         412 $self->{orig_request_params} = $params;
52 185         5464 delete( $self->{orig_request_params}->{interp} );
53             }
54              
55 20     20   6171 method _build_result () {
  127     127   235  
  127         188  
56 127         3219 return $self->interp->result_class->new;
57             }
58              
59             #
60             # PUBLIC METHODS
61             #
62              
63 20     20   6243 method abort ($aborted_value) {
  24     24   40  
  24         38  
  24         28  
64 24         265 Mason::Exception::Abort->throw(
65             error => 'Request->abort was called',
66             aborted_value => $aborted_value
67             );
68             }
69              
70 20     20   6691 method aborted ($err) {
  31     31   57  
  31         60  
  31         74  
71 31   100     319 return blessed($err) && $err->isa('Mason::Exception::Abort');
72             }
73              
74 20     20   6759 method add_cleanup ($code) {
  1     1   2  
  1         2  
  1         1  
75 1         2 push( @{ $self->{cleanups} }, $code );
  1         4  
76             }
77              
78 20     20   6323 method cache () {
  0     0   0  
  0         0  
79 0         0 die 'caching is now in the cache plugin (Mason::Plugin::Cache)';
80             }
81              
82 20     20   6388 method capture ($code) {
  36     36   44  
  36         46  
  36         36  
83 36 50 33     184 croak "capture() expects a code reference" unless defined($code) && ref($code) eq 'CODE';
84 36         40 my $output;
85             {
86 36         32 $self->_push_buffer;
  36         91  
87 36     36   156 scope_guard { $output = ${ $self->_current_buffer }; $self->_pop_buffer; };
  36         45  
  36         91  
  36         91  
88 36         65 $code->();
89             }
90 36         212 return $output;
91             }
92              
93 20     20   7496 method clear_and_abort () {
  21     21   35  
  21         32  
94 21         76 $self->clear_buffer;
95 21         85 $self->abort(@_);
96             }
97              
98 20     20   5829 method clear_buffer () {
  24     24   37  
  24         33  
99 24         27 foreach my $buffer ( @{ $self->buffer_stack } ) {
  24         594  
100 24         77 $$buffer = '';
101             }
102             }
103              
104 20     20   7743 method comp () {
  37     37   77  
  37         53  
105 37         196 $self->construct(@_)->main();
106             }
107              
108 20     20   6151 method comp_exists ($path) {
  6     6   6  
  6         8  
  6         2  
109 6         147 return $self->interp->comp_exists( $self->rel_to_abs($path) );
110             }
111              
112 20     20   6283 method construct () {
  37     37   59  
  37         47  
113 37         59 my $path = shift;
114 37 100       146 my $compc = $self->load($path)
115             or $self->_comp_not_found($path);
116 34         1625 return $compc->new( @_, 'm' => $self );
117             }
118              
119 20     20   6215 method current_comp_class () {
  19     19   28  
  19         25  
120 19         27 my $cnt = 1;
121 19         25 while (1) {
122 82 100       156 if ( my $pkg = ( caller($cnt) )[0] ) {
123 81 100 66     2010 return $pkg if $pkg->isa('Mason::Component') && $pkg ne 'Mason::Component';
124             }
125             else {
126 1         130 confess("cannot determine current_comp_class from stack");
127             }
128 63         116 $cnt++;
129             }
130             }
131              
132 20     20   7346 method decline () {
  21     21   45  
  21         27  
133 21         529 $self->declined(1);
134 21         73 $self->clear_and_abort;
135             }
136              
137 20     20   5727 method filter () {
  2     2   4  
  2         3  
138 2         8 $self->_apply_filters(@_);
139             }
140              
141 20     20   5904 method flush_buffer () {
  127     127   784  
  127         190  
142 127         686 my $request_buffer = $self->_request_buffer;
143 127         516 $self->process_output($request_buffer);
144 127 100       3807 $self->out_method->( $$request_buffer, $self )
145             if length $$request_buffer;
146 127         345 $$request_buffer = '';
147             }
148              
149 20     20   6606 method go () {
  3     3   5  
  3         3  
150 3         14 $self->clear_buffer;
151 3         4 my %request_params = ( %{ $self->{orig_request_params} } );
  3         10  
152 3 100       10 if ( ref( $_[0] ) eq 'HASH' ) {
153 1         2 %request_params = ( %request_params, %{ shift(@_) } );
  1         4  
154             }
155 3         12 $self->{go_result} = $self->_run_subrequest( \%request_params, @_ );
156 3         14 $self->abort();
157             }
158              
159 20     20   7435 method load ($path) {
  37     37   62  
  37         60  
  37         54  
160 37         1062 my $compc = $self->interp->load( $self->rel_to_abs($path) );
161             }
162              
163 20     20   6381 method log () {
  1     1   2  
  1         1  
164 1         5 return $self->current_comp_class->cmeta->log();
165             }
166              
167 20     20   5730 method notes () {
  5     5   5  
  5         9  
168 5 50       11 return $self->{notes}
169             unless @_;
170 5         6 my $key = shift;
171 5 100       16 return $self->{notes}->{$key} unless @_;
172 2         7 return $self->{notes}->{$key} = shift;
173             }
174              
175 20     20   6358 method print () {
  44     44   62  
  44         49  
176 44         126 my $buffer = $self->_current_buffer;
177 44         96 for (@_) {
178 44 100       217 $$buffer .= $_ if defined;
179             }
180             }
181              
182 20     20   6630 method rel_to_abs ($path) {
  49     49   76  
  49         77  
  49         50  
183 49 100       232 $path = join( "/", $self->current_comp_class->cmeta->dir_path, $path )
184             unless substr( $path, 0, 1 ) eq '/';
185 49         2771 return $path;
186             }
187              
188 20     20   7265 method scomp () {
  3     3   4  
  3         4  
189 3         7 my @params = @_;
190 3     3   21 my $buf = $self->capture( sub { $self->comp(@params) } );
  3         13  
191 3         19 return $buf;
192             }
193              
194 20     20   6688 method visit () {
  3     3   5  
  3         4  
195 3         4 my $buf;
196 3         3 my %request_params = ( %{ $self->{orig_request_params} }, out_method => \$buf );
  3         13  
197 3 100       8 if ( ref( $_[0] ) eq 'HASH' ) {
198 1         2 %request_params = ( %request_params, %{ shift(@_) } );
  1         4  
199             }
200 3         12 my $result = $self->_run_subrequest( \%request_params, @_ );
201 3         12 $self->print($buf);
202 3         73 return $result;
203             }
204              
205             #
206             # MODIFIABLE METHODS
207             #
208              
209 20     20   7059 method cleanup_request () {
  184     184   333  
  184         219  
210 184         4831 $self->interp->_flush_load_cache();
211 184         6876 foreach my $cleanup ( @{ $self->{cleanups} } ) {
  184         1350  
212             try {
213 1     1   31 $cleanup->($self);
214             }
215             catch {
216 0     0   0 warn "error during request cleanup: $_";
217 1         9 };
218             }
219             }
220              
221 20     20   7819 method construct_page_component ($compc, $args) {
  158     158   291  
  158         270  
  158         228  
222 158         5199 return $compc->new( %$args, 'm' => $self );
223             }
224              
225 20     20   6525 method catch_abort ($code) {
  158     158   288  
  158         272  
  158         246  
226 158         294 my $retval;
227             try {
228 158     158   4985 $retval = $code->();
229             }
230             catch {
231 31     31   423 my $err = $_;
232 31 100       159 if ( $self->aborted($err) ) {
233 24         547 $retval = $err->aborted_value;
234             }
235             else {
236 7         52 die $err;
237             }
238 158         1240 };
239 151         3371 return $retval;
240             }
241              
242 20     20   8519 method match_request_path ($request_path) {
  205     205   357  
  205         344  
  205         283  
243 205         5003 $self->interp->match_request_path->( $self, $request_path );
244             }
245              
246 20     20   6217 method process_output ($outref) {
  127     127   189  
  127         198  
  127         190  
247              
248             # No-op by default
249             }
250              
251 20     20   6101 method run () {
  184     184   305  
  184         241  
252              
253             # Get path and either hash or hashref of arguments
254             #
255 184         277 my $request_path = shift;
256 184         4984 $self->interp->_assert_absolute_path($request_path);
257 184         305 my $request_args;
258 184 50 33     765 if ( @_ == 1 && reftype( $_[0] ) eq 'HASH' ) {
259 0         0 $request_args = shift;
260             }
261             else {
262 184         431 $request_args = {@_};
263             }
264              
265             # Save off the requested path and args
266             #
267 184         500 $self->{request_path} = $request_path;
268 184         387 $self->{request_args} = $request_args;
269              
270             # Localize current_request and current_buffer until end of scope. Use a guard
271             # because 'local' doesn't work with the aliases inside components.
272             #
273 184         289 my $save_current_request = $current_request;
274 184         248 my $save_current_buffer = $current_buffer;
275 184     184   1416 scope_guard { $current_request = $save_current_request; $current_buffer = $save_current_buffer };
  184         388  
  184         4894  
276 184         279 $current_request = $self;
277 184         889 $self->_push_buffer();
278              
279             # Clean up after request
280             #
281 184     184   809 scope_guard { $self->cleanup_request() };
  184         14731  
282              
283             # Flush interp load cache
284             #
285 184         5283 $self->interp->_flush_load_cache();
286              
287             # Check the static_source touch file, if it exists, before the
288             # first component is loaded.
289             #
290 184         11541 $self->interp->_check_static_source_touch_file();
291              
292             # Turn request path into a page component
293             #
294 205         1000 match_request_path:
295             my $page_path = $self->match_request_path($request_path);
296 158         4522 my $page_compc = $self->interp->load($page_path);
297 158 50       5508 $log->debugf( "starting request with component '%s'", $page_path )
298             if $log->is_debug;
299              
300             $self->catch_abort(
301             sub {
302              
303             # Construct page component
304             #
305 158     158   902 my $page = $self->construct_page_component( $page_compc, $request_args );
306 157         458 $self->{page} = $page;
307              
308             # Dispatch to page component, with 'print' tied to component output.
309             #
310 157         1524 $self->with_tied_print( sub { $page->handle } );
  157         1507  
311             }
312 158         2248 );
313              
314             # If declined, retry match
315             #
316 151 100       5178 if ( $self->declined ) {
317 21         474 $self->declined(0);
318 21         61 $self->{declined_paths}->{$page_path} = 1;
319 21         148 goto match_request_path;
320             }
321              
322             # If go() was called in this request, return the result of the subrequest
323             #
324 130 100       3791 return $self->go_result if defined( $self->go_result );
325              
326             # Send output to its final destination
327             #
328 127         690 $self->flush_buffer;
329              
330 127         3144 return $self->result;
331             }
332              
333 20     20   13426 method with_tied_print ($code) {
  157     157   264  
  157         244  
  157         227  
334 157         437 local *TH;
335 157         1658 tie *TH, 'Mason::TieHandle';
336 157         669 my $old = select TH;
337 157     157   1069 scope_guard { select $old };
  157         32541  
338 157         457 return $code->();
339             }
340              
341             #
342             # PRIVATE METHODS
343             #
344              
345 20     20   7260 method _apply_one_filter ($filter, $yield) {
  42     42   43  
  42         59  
  42         45  
346 42         38 my $filtered_output;
347 42 50       91 if ( ref($yield) ne 'CODE' ) {
348 0 0       0 my $orig_yield = defined($yield) ? $yield : '';
349 0     0   0 $yield = sub { $orig_yield };
  0         0  
350             }
351 42 100 66     158 if ( ref($filter) eq 'CODE' ) {
    100          
352 32         43 local $_ = $yield->();
353 32 50       72 $_ = '' if !defined($_);
354 32         66 $filtered_output = $filter->($_);
355             }
356             elsif ( blessed($filter) && $filter->can('apply_filter') ) {
357 9         28 $filtered_output = $filter->apply_filter($yield);
358             }
359             else {
360 1         16 die "'$filter' is neither a code ref nor a filter object";
361             }
362 41         136 return $filtered_output;
363             }
364              
365 20     20   9470 method _apply_filters () {
  78     78   78  
  78         67  
366 78         85 my $yield = pop(@_);
367 78 100       168 if ( ref($yield) ne 'CODE' ) {
368 1 50       22 my $orig_yield = defined($yield) ? $yield : '';
369 1     1   5 $yield = sub { $orig_yield };
  1         3  
370             }
371 78 100       125 if ( !@_ ) {
372 36         60 return $yield->();
373             }
374             else {
375 42         58 my $filter = pop(@_);
376 42     42   155 return $self->_apply_filters( @_, sub { $self->_apply_one_filter( $filter, $yield ) } );
  42         112  
377             }
378             }
379              
380 20     20   7994 method _apply_filters_to_output () {
  22     22   38  
  22         22  
381 22         30 my $output_method = pop(@_);
382             my $yield = sub {
383 27     27   37 my @args = @_;
384 27         130 $self->capture( sub { $output_method->(@args) } );
  27         99  
385 22         96 };
386 22         77 my $filtered_output = $self->_apply_filters( @_, $yield );
387 21         87 $self->print($filtered_output);
388             }
389              
390 20     20   7633 method _comp_not_found ($path) {
  3     3   53  
  3         7  
  3         5  
391 3         82 croak sprintf( "could not find component for path '%s' - component root is [%s]",
392 3         7 $path, join( ", ", @{ $self->interp->comp_root } ) );
393             }
394              
395 20     20   6760 method _current_buffer () {
  116     116   118  
  116         90  
396 116         266 $self->{buffer_stack}->[-1];
397             }
398              
399 20     20   6227 method _pop_buffer () {
  36     36   38  
  36         32  
400 36         43 pop( @{ $self->{buffer_stack} } );
  36         55  
401 36         50 $current_buffer = $self->_current_buffer;
402             }
403              
404 20     20   7718 method _push_buffer () {
  220     220   521  
  220         273  
405 220         359 my $s = '';
406 220         276 push( @{ $self->{buffer_stack} }, \$s );
  220         615  
407 220         429 $current_buffer = \$s;
408             }
409              
410 20     20   6472 method _request_buffer () {
  129     129   235  
  129         174  
411 129         396 $self->{buffer_stack}->[0];
412             }
413              
414 20     20   7061 method _reset_next_id () {
  6     6   9  
  6         12  
415              
416             # for testing
417 6         12 $next_id = 0;
418             }
419              
420 20     20   6203 method _run_subrequest () {
  6     6   10  
  6         7  
421 6         7 my $request_params = shift(@_);
422 6         23 my $path = $self->rel_to_abs( shift(@_) );
423 6         141 $self->interp->run( $request_params, $path, @_ );
424             }
425              
426             __PACKAGE__->meta->make_immutable();
427              
428             1;
429              
430             __END__
431              
432             =pod
433              
434             =head1 NAME
435              
436             Mason::Request - Mason Request Class
437              
438             =head1 SYNOPSIS
439              
440             $m->abort (...)
441             $m->comp (...)
442             etc.
443              
444             =head1 DESCRIPTION
445              
446             Mason::Request represents a single request for a page, and is the access point
447             for most Mason features not provided by syntactic tags.
448              
449             A Mason request is created when you call C<< $interp->run >>, or in a web
450             environment, for each new web request. A new (sub-)request is also created when
451             you call L<visit|/visit> or L<go|/go> on the current request.
452              
453             Inside a component you can access the current request object via the global
454             C<$m>. Outside of a component, you can use the class method
455             C<Mason::Request-E<gt>current_request>.
456              
457             =head1 COMPONENT PATHS
458              
459             The methods L<comp|/comp>, L<comp_exists|/comp_exists>,
460             L<construct|/construct>, L<go|/go>, L<load|/load>, and L<visit|/visit> take a
461             component path argument. If the path does not begin with a '/', then it is made
462             absolute based on the current component path (using L<rel_to_abs|/rel_to_abs>).
463              
464             Component paths are like URL paths, and always use a forward slash (/) as the
465             separator, regardless of what your operating system uses.
466              
467             =head1 PARAMETERS TO THE new() CONSTRUCTOR
468              
469             These parameters would normally be passed in an initial hashref to C<<
470             $interp->run >>, C<< $m->visit >>, or C<< $m->go >>.
471              
472             =over
473              
474             =item out_method
475              
476             Indicates where to send the page output. If out_method is a scalar reference,
477             output is appended to the scalar. If out_method is a code reference, the code
478             is called with the output string. For example, to send output to a file called
479             "mason.out":
480              
481             open(my $fh, ">", "mason.out);
482             ...
483             out_method => sub { $fh->print($_[0]) }
484              
485             When C<out_method> is unspecified, the output can be obtained from the
486             L<Mason::Result|Mason::Result> object returned from C<< $interp->run >>.
487              
488             =back
489              
490             =head1 PUBLIC METHODS
491              
492             =over
493              
494             =item abort ()
495              
496             Ends the current request, finishing the page without returning through
497             components.
498              
499             C<abort> is implemented by throwing an C<Mason::Exception::Abort> object and
500             can thus be caught by C<eval>. The C<aborted> method is a shortcut for
501             determining whether a caught error was generated by C<abort>.
502              
503             =item aborted ([$err])
504              
505             Returns true or undef indicating whether the specified C<$err> was generated by
506             C<abort>. If no C<$err> was passed, uses C<$@>.
507              
508             In this L<Try::Tiny|Try::Tiny> code, we catch and process fatal errors while
509             letting C<abort> exceptions pass through:
510              
511             try {
512             code_that_may_fail_or_abort()
513             } catch {
514             die $_ if $m->aborted($_);
515             # handle fatal errors...
516             };
517              
518             =item add_cleanup (code)
519              
520             Add a code reference to be executed when the request is L<cleaned
521             up|/cleanup_request>.
522              
523             =item clear_and_abort ()
524              
525             This method is syntactic sugar for calling C<clear_buffer()> and then
526             C<abort()>. If you are aborting the request because of an error (or, in a web
527             environment, to do a redirect), you will often want to clear the buffer first
528             so that any output generated up to that point is not sent to the client.
529              
530             =item capture (code)
531              
532             Execute the I<code>, capturing and returning any Mason output instead of
533             outputting it. e.g. the following
534              
535             my $buf = $m->capture(sub { $m->comp('/foo') });
536              
537             is equivalent to
538              
539             my $buf = $m->scomp('/foo');
540              
541             =item clear_buffer ()
542              
543             Clears the Mason output buffer. Any output sent before this line is discarded.
544             Useful for handling error conditions that can only be detected in the middle of
545             a request.
546              
547             clear_buffer is, of course, thwarted by L<flush_buffer|/flush_buffer>.
548              
549             =item comp (path[, params ...])
550              
551             Creates a new instance of the component designated by I<path>, and calls its
552             C<main> method. I<params>, if any, are passed to the constructor.
553              
554             The C<< <& &> >> tag provides a shortcut for C<$m-E<gt>comp>.
555              
556             =item comp_exists (path)
557              
558             Makes the component I<path> absolute if necessary, and calls L<Interp
559             comp_exists|Mason::Interp/comp_exists> to determine whether a component exists
560             at that path.
561              
562             =item current_comp_class ()
563              
564             Returns the current component class. This is determined by walking up the Perl
565             caller() stack until the first Mason::Component subclass is found.
566              
567             =item current_request ()
568              
569             This class method returns the C<Mason::Request> currently in use. If called
570             when no Mason request is active it will return C<undef>.
571              
572             =item construct (path[, params ...])
573              
574             Constructs and return a new instance of the component designated by I<path>.
575             I<params>, if any, are passed to the constructor. Throws an error if I<path>
576             does not exist.
577              
578             =item decline ()
579              
580             Clears the output buffer and tries the current request again, but acting as if
581             the previously chosen page component(s) do not exist.
582              
583             For example, if the following components exist:
584              
585             /news/sports.mc
586             /news/dhandler.mc
587             /dhandler.mc
588              
589             then a request for path C</news/sports> will initially resolve to
590             C</news/sports.mc>. A call to C<< $m->decline >> would restart the request and
591             resolve to C</news/dhandler.mc>, a second C<< $m->decline >> would resolve to
592             C</dhandler.mc>, and a third would throw a "not found" error.
593              
594             =item filter (filter_expr, [filter_expr...], string|coderef)
595              
596             Applies one or more filters to a string or to a coderef that returns a string.
597              
598             my $filtered_string = $m->filter($.Trim, $.NoBlankLines, $string);
599              
600             =item flush_buffer ()
601              
602             Flushes the main output buffer. Anything currently in the buffer is sent to the
603             request's L<out_method|/out_method>.
604              
605             Note that anything output within a C<< $m->scomp >> or C<< $m->capture >> will
606             not have made it to the main output buffer, and thus cannot be flushed.
607              
608             =item go ([request params], path, args...)
609              
610             Performs an internal redirect. Clears the output buffer, runs a new request for
611             the given I<path> and I<args>, and then L<aborts|/abort> when that request is
612             done.
613              
614             The first argument may optionally be a hashref of parameters which are passed
615             to the C<Mason::Request> constructor.
616              
617             See also L<visit|/visit>.
618              
619             =item interp ()
620              
621             Returns the L<Interp|Mason::Interp> object associated with this request.
622              
623             =item load (path)
624              
625             Makes the component I<path> absolute if necessary, and calls L<Interp
626             load|Mason::Interp/load> to load the component class associated with the path.
627              
628             =item log ()
629              
630             Returns a C<Log::Any> logger with a log category specific to the current
631             component. The category for a component "/foo/bar" would be
632             "Mason::Component::foo::bar".
633              
634             =item notes ([key[, value]])
635              
636             The C<notes()> method provides a place to store application data between
637             components - essentially, a hash which persists for the duration of the
638             request.
639              
640             C<notes($key, $value)> stores a new entry in the hash; C<notes($key)> returns a
641             previously stored value; and C<notes()> without any arguments returns a
642             reference to the entire hash of key-value pairs.
643              
644             Consider storing this kind of data in a read-write attribute of the page
645             component.
646              
647             =item print (string)
648              
649             Add the given I<string> to the Mason output buffer. This happens implicitly for
650             all content placed in the main component body.
651              
652             =item page ()
653              
654             Returns the page component originally called in the request.
655              
656             =item path_info ()
657              
658             Returns the remainder of the request path beyond the path of the page
659             component, with no leading slash. e.g. If a request for '/foo/bar/baz' resolves
660             to "/foo.mc", the path_info is "bar/baz". For an exact match, it will contain
661             the empty string (never undef), so you can determine whether there's a
662             path_info with
663              
664             if ( length($m->path_info) )
665              
666             =item rel_to_abs (path)
667              
668             Converts a component I<path> to absolute form based on the current component,
669             if it does not already begin with a '/'.
670              
671             =item request_args ()
672              
673             Returns the original hashref of arguments passed to the request, e.g. via C<<
674             $interp->run >>.
675              
676             =item request_path ()
677              
678             Returns the original path passed to the request, e.g. in C<< $interp->run >>.
679              
680             =item scomp (comp, args...)
681              
682             Like L<comp|Mason::Request/item_comp>, but returns the component output as a
683             string instead of printing it. (Think sprintf versus printf.)
684              
685             See also L<capture|/capture>.
686              
687             =item visit ([request params], path, args...)
688              
689             Performs a subrequest with the given I<path> and I<args>, with output being
690             sent to the current output buffer.
691              
692             The first argument may optionally be a hashref of parameters which are passed
693             to the C<Mason::Request> constructor. e.g. to capture the output of the
694             subrequest:
695              
696             $m->visit({out_method => \my $buffer}, ...);
697              
698             See also L<go|/go>.
699              
700             =back
701              
702             =head1 MODIFIABLE METHODS
703              
704             These methods are not intended to be called externally, but may be useful to
705             modify with method modifiers in L<plugins|Mason::Manual::Plugins> and
706             L<subclasses|Mason::Manual::Subclasses>. Their APIs will be kept as stable as
707             possible.
708              
709             =over
710              
711             =item cleanup_request ()
712              
713             A place to perform cleanup duties when the request finishes or dies with an
714             error, even if the request object is not immediately destroyed. Includes
715             anything registered with L<add_cleanup|/add_cleanup>.
716              
717             =item construct_page_component ($compc, $args)
718              
719             Constructs the page component of class I<$compc>, with hashref of constructor
720             arguments I<$args>.
721              
722             =item match_request_path ($request_path)
723              
724             Given a top level I<$request_path>, return a corresponding component path or
725             undef if none was found. Search includes dhandlers and index files. See
726             L<Mason::Manual::RequestDispatch>.
727              
728             =item process_output ($outref)
729              
730             This method is called on the output buffer right before it is sent to its final
731             destination. I<$outref> is a reference to the output string; the method can
732             modify it as desired.
733              
734             =item run ($request_path, args)
735              
736             Runs the request with I<$request_path> and I<args>, where the latter can be
737             either a hashref or a hash. This is generally called via << $interp->run >>.
738              
739             =item with_tied_print ($code)
740              
741             Execute the given I<$code> with the current selected filehandle ('print') tied
742             to the Mason output stream. You could disable the filehandle selection by
743             overriding this to just call I<$code>.
744              
745             =back
746              
747             =head1 SEE ALSO
748              
749             L<Mason|Mason>
750              
751             =head1 AUTHOR
752              
753             Jonathan Swartz <swartz@pobox.com>
754              
755             =head1 COPYRIGHT AND LICENSE
756              
757             This software is copyright (c) 2012 by Jonathan Swartz.
758              
759             This is free software; you can redistribute it and/or modify it under
760             the same terms as the Perl 5 programming language system itself.
761              
762             =cut