1=head1 NAME 2 3HTTP Handlers 4 5=head1 Description 6 7This chapter explains how to implement the HTTP protocol handlers in 8mod_perl. 9 10 11=head1 HTTP Request Handler Skeleton 12 13All HTTP Request handlers have the following structure: 14 15 package MyApache2::MyHandlerName; 16 17 # load modules that are going to be used 18 use ...; 19 20 # compile (or import) constants 21 use Apache2::Const -compile => qw(OK); 22 23 sub handler { 24 my $r = shift; 25 26 # handler code comes here 27 28 return Apache2::Const::OK; # or another status constant 29 } 30 1; 31 32First, the package is declared. Next, the modules that are going to be 33used are loaded and constants compiled. 34 35The handler itself coming next and usually it receives the only 36argument: the 37C<L<Apache2::RequestRec|docs::2.0::api::Apache2::RequestRec>> object. 38If the handler is declared as L<a method handler 39|docs::2.0::user::coding::coding/Method_Handlers>: 40 41 sub handler : method { 42 my ($class, $r) = @_; 43 44the handler receives two arguments: the class name and the 45C<L<Apache2::RequestRec|docs::2.0::api::Apache2::RequestRec>> object. 46 47The handler ends with L<a return 48code|docs::2.0::user::handlers::intro/Stacked_Handlers> and the file 49is ended with C<1;> to return true when it gets loaded. 50 51 52 53 54 55 56=head1 HTTP Request Cycle Phases 57 58Those familiar with mod_perl 1.0 will find the HTTP request cycle in 59mod_perl 2.0 to be almost identical to the mod_perl 1.0's model. The 60different things are: 61 62=over 63 64=item * 65 66a new directive C<L<PerlMapToStorageHandler|/PerlMapToStorageHandler>> 67was added to match the new phase I<map_to_storage> added by Apache 682.0. 69 70=item * 71 72the C<PerlHandler> directive has been renamed to 73C<PerlResponseHandler> to better match the corresponding Apache phase 74name (I<response>). 75 76=item * 77 78the I<response> phase now includes filtering. 79 80=back 81 82The following diagram depicts the HTTP request life cycle and 83highlights which handlers are available to mod_perl 2.0: 84 85=for html 86<img src="http_cycle.gif" width="600" height="560" 87 align="middle" alt="HTTP cycle"><br><br> 88 89From the diagram it can be seen that an HTTP request is processed by 9012 phases, executed in the following order: 91 92=over 93 94=item 1 PerlPostReadRequestHandler (PerlInitHandler) 95 96=item 2 PerlTransHandler 97 98=item 3 PerlMapToStorageHandler 99 100=item 4 PerlHeaderParserHandler (PerlInitHandler) 101 102=item 5 PerlAccessHandler 103 104=item 6 PerlAuthenHandler 105 106=item 7 PerlAuthzHandler 107 108=item 8 PerlTypeHandler 109 110=item 9 PerlFixupHandler 111 112=item 10 PerlResponseHandler 113 114=item 11 PerlLogHandler 115 116=item 12 PerlCleanupHandler 117 118=back 119 120It's possible that the cycle will not be completed if any of the 121phases terminates it, usually when an error happens. In that case 122Apache skips to the logging phase (mod_perl executes all registered 123C<PerlLogHandler> handlers) and finally the cleanup phase happens. 124 125Notice that when the response handler is reading the input data it can 126be filtered through request input filters, which are preceded by 127connection input filters if any. Similarly the generated response is 128first run through request output filters and eventually through 129connection output filters before it's sent to the client. We will talk 130about filters in detail later in L<the dedicated to filters 131chapter|docs::2.0::user::handlers::filters>. 132 133Before discussing each handler in detail remember that if you use 134L<the stacked handlers 135feature|docs::2.0::user::handlers::intro/Stacked_Handlers> all 136handlers in the chain will be run as long as they return C<Apache2::Const::OK> 137or C<Apache2::Const::DECLINED>. Because stacked handlers is a special case. So 138don't be surprised if you've returned C<Apache2::Const::OK> and the next 139handler was still executed. This is a feature, not a bug. 140 141Now let's discuss each of the mentioned handlers in detail. 142 143 144 145 146 147 148 149 150 151 152 153 154 155=head2 PerlPostReadRequestHandler 156 157The I<post_read_request> phase is the first request phase and happens 158immediately after the request has been read and HTTP headers were 159parsed. 160 161This phase is usually used to do processing that must happen once per 162request. For example C<Apache2::Reload> is usually invoked at this 163phase to reload modified Perl modules. 164 165This phase is of type 166C<L<RUN_ALL|docs::2.0::user::handlers::intro/item_RUN_ALL>>. 167 168The handler's configuration scope is 169C<L<SRV|docs::2.0::user::config::config/item_SRV>>, because at this 170phase the request has not yet been associated with a particular 171filename or directory. 172 173B<Arguments> 174 175See the L<HTTP Request Handler Skeleton|docs::2.0::user::handlers::http/HTTP_Request_Handler_Skeleton> for a description of handler arguments. 176 177B<Return> 178 179See L<Stacked Handlers|docs::2.0::user::handlers::intro/Stacked_Handlers> 180for a description of handler return codes. 181 182B<Examples> 183 184Now, let's look at an example. Consider the following registry script: 185 186 #file:touch.pl 187 #------------- 188 use strict; 189 use warnings; 190 191 use Apache2::ServerUtil (); 192 use Apache2::RequestIO (); 193 use File::Spec::Functions qw(catfile); 194 195 my $r = shift; 196 $r->content_type('text/plain'); 197 198 my $conf_file = catfile Apache2::ServerUtil::server_root, 199 "conf", "httpd.conf"; 200 201 printf "$conf_file is %0.2f minutes old\n", 60*24*(-M $conf_file); 202 203This registry script is supposed to print when the last time 204I<httpd.conf> has been modified, compared to the start of the request 205process time. If you run this script several times you might be 206surprised that it reports the same value all the time. Unless the 207request happens to be served by a recently started child process which 208will then report a different value. But most of the time the value 209won't be reported correctly. 210 211This happens because the C<-M> operator reports the difference between 212file's modification time and the value of a special Perl variable 213C<$^T>. When we run scripts from the command line, this variable is 214always set to the time when the script gets invoked. Under mod_perl 215this variable is getting preset once when the child process starts and 216doesn't change since then, so all requests see the same time, when 217operators like C<-M>, C<-C> and C<-A> are used. 218 219Armed with this knowledge, in order to make our code behave similarly 220to the command line programs we need to reset C<$^T> to the request's 221start time, before C<-M> is used. We can change the script itself, but 222what if we need to do the same change for several other scripts and 223handlers? A simple C<PerlPostReadRequestHandler> handler, which will 224be executed as the very first thing of each requests, comes handy 225here: 226 227 #file:MyApache2/TimeReset.pm 228 #-------------------------- 229 package MyApache2::TimeReset; 230 231 use strict; 232 use warnings; 233 234 use Apache2::RequestRec (); 235 236 use Apache2::Const -compile => 'OK'; 237 238 sub handler { 239 my $r = shift; 240 $^T = $r->request_time; 241 return Apache2::Const::OK; 242 } 243 1; 244 245We could do: 246 247 $^T = time(); 248 249But to make things more efficient we use C<$r-E<gt>request_time> since 250the request object C<$r> already stores the request's start time, so 251we get it without performing an additional system call. 252 253To enable it just add to I<httpd.conf>: 254 255 PerlPostReadRequestHandler MyApache2::TimeReset 256 257either to the global section, or to the C<E<lt>VirtualHostE<gt>> 258section if you want this handler to be run only for a specific virtual 259host. 260 261 262 263 264 265 266=head2 PerlTransHandler 267 268The I<translate> phase is used to perform the manipulation of a 269request's URI. If no custom handler is provided, the server's standard 270translation rules (e.g., C<Alias> directives, mod_rewrite, etc.) will 271be used. A C<PerlTransHandler> handler can alter the default 272translation mechanism or completely override it. This is also a good 273place to register new handlers for the following phases based on the 274URI. C<L<PerlMapToStorageHandler|/PerlMapToStorageHandler>> is to be 275used to override the URI to filename translation. 276 277This phase is of type 278C<L<RUN_FIRST|docs::2.0::user::handlers::intro/item_RUN_FIRST>>. 279 280The handler's configuration scope is 281C<L<SRV|docs::2.0::user::config::config/item_SRV>>, because at this 282phase the request has not yet been associated with a particular 283filename or directory. 284 285B<Arguments> 286 287See the L<HTTP Request Handler Skeleton|docs::2.0::user::handlers::http/HTTP_Request_Handler_Skeleton> for a description of handler arguments. 288 289B<Return> 290 291See L<Stacked Handlers|docs::2.0::user::handlers::intro/Stacked_Handlers> 292for a description of handler return codes. 293 294B<Examples> 295 296There are many useful things that can be performed at this 297stage. Let's look at the example handler that rewrites request URIs, 298similar to what mod_rewrite does. For example, if your web-site was 299originally made of static pages, and now you have moved to a dynamic 300page generation chances are that you don't want to change the old 301URIs, because you don't want to break links for those who link to your 302site. If the URI: 303 304 http://example.com/news/20021031/09/index.html 305 306is now handled by: 307 308 http://example.com/perl/news.pl?date=20021031;id=09;page=index.html 309 310the following handler can do the rewriting work transparent to 311I<news.pl>, so you can still use the former URI mapping: 312 313 #file:MyApache2/RewriteURI.pm 314 #--------------------------- 315 package MyApache2::RewriteURI; 316 317 use strict; 318 use warnings; 319 320 use Apache2::RequestRec (); 321 322 use Apache2::Const -compile => qw(DECLINED); 323 324 sub handler { 325 my $r = shift; 326 327 my ($date, $id, $page) = $r->uri =~ m|^/news/(\d+)/(\d+)/(.*)|; 328 $r->uri("/perl/news.pl"); 329 $r->args("date=$date;id=$id;page=$page"); 330 331 return Apache2::Const::DECLINED; 332 } 333 1; 334 335The handler matches the URI and assigns a new URI via C<$r-E<gt>uri()> 336and the query string via C<$r-E<gt>args()>. It then returns 337C<Apache2::Const::DECLINED>, so the next translation handler will get 338invoked, if more rewrites and translations are needed. 339 340Of course if you need to do a more complicated rewriting, this handler 341can be easily adjusted to do so. 342 343To configure this module simply add to I<httpd.conf>: 344 345 PerlTransHandler +MyApache2::RewriteURI 346 347 348 349 350 351 352=head2 PerlMapToStorageHandler 353 354The I<map_to_storage> phase is used to perform the translation of a 355request's URI into a corresponding filename. If no custom handler is 356provided, the server will try to walk the filesystem trying to find 357what file or directory corresponds to the request's URI. Since usually 358mod_perl handler don't have corresponding files on the filesystem, you 359will want to shortcut this phase and save quite a few CPU cycles. 360 361This phase is of type 362C<L<RUN_FIRST|docs::2.0::user::handlers::intro/item_RUN_FIRST>>. 363 364The handler's configuration scope is 365C<L<SRV|docs::2.0::user::config::config/item_SRV>>, because at this 366phase the request has not yet been associated with a particular 367filename or directory. 368 369B<Arguments> 370 371See the L<HTTP Request Handler Skeleton|docs::2.0::user::handlers::http/HTTP_Request_Handler_Skeleton> for a description of handler arguments. 372 373B<Return> 374 375See L<Stacked Handlers|docs::2.0::user::handlers::intro/Stacked_Handlers> 376for a description of handler return codes. 377 378B<Examples> 379 380For example if you don't want Apache to try to attempt to translate 381URI into a filename, just add a handler: 382 383 PerlMapToStorageHandler MyApache2::NoTranslation 384 385using the following code: 386 387 #file:MyApache2/NoTranslation.pm 388 #------------------------------ 389 package MyApache2::NoTranslation; 390 391 use strict; 392 use warnings FATAL => 'all'; 393 394 use Apache2::Const -compile => qw(OK); 395 396 sub handler { 397 my $r = shift; 398 399 # skip ap_directory_walk stat() calls 400 return Apache2::Const::OK; 401 } 402 1; 403 404But this can be done from F<httpd.conf> too! 405 406 PerlMapToStorageHandler Apache2::Const::OK 407 408If you haven't already compiled C<Apache2::Const::OK> elsewhere, you 409should add: 410 411 <Perl> 412 use Apache2::Const -compile => qw(OK); 413 </Perl> 414 415Apache also uses this phase to handle C<TRACE> requests. So if you 416shortcut it, C<TRACE> calls will be not handled. In case you need to 417handle such, you may rewrite it as: 418 419 #file:MyApache2/NoTranslation2.pm 420 #------------------------------- 421 package MyApache2::NoTranslation2; 422 423 use strict; 424 use warnings FATAL => 'all'; 425 426 use Apache2::RequestRec (); 427 428 use Apache2::Const -compile => qw(DECLINED OK M_TRACE); 429 430 sub handler { 431 my $r = shift; 432 433 return Apache2::Const::DECLINED 434 if $r->method_number == Apache2::Const::M_TRACE; 435 436 # skip ap_directory_walk stat() calls 437 return Apache2::Const::OK; 438 } 439 1; 440 441BTW, the HTTP TRACE method asks a web server to echo the contents of 442the request back to the client for debugging purposes. i.e., the 443complete request, including HTTP headers, is returned in the 444entity-body of a TRACE response. Attackers may abuse HTTP TRACE 445functionality to gain access to information in HTTP headers such as 446cookies and authentication data. In the presence of other cross-domain 447vulnerabilities in web browsers, sensitive header information could be 448read from any domains that support the HTTP TRACE method. 449 450Another way to prevent the core translation is to set 451C<$r-E<gt>filename()> to some value, which can also be done in the 452C<L<PerlTransHandler|/PerlTransHandler>>, if you are already using it. 453 454 455 456 457 458 459 460 461=head2 PerlHeaderParserHandler 462 463The I<header_parser> phase is the first phase to happen after the 464request has been mapped to its C<E<lt>LocationE<gt>> (or an equivalent 465container). At this phase the handler can examine the request headers 466and to take a special action based on these. For example this phase 467can be used to block evil clients targeting certain resources, while 468little resources were wasted so far. 469 470This phase is of type 471C<L<RUN_ALL|docs::2.0::user::handlers::intro/item_RUN_ALL>>. 472 473The handler's configuration scope is 474C<L<DIR|docs::2.0::user::config::config/item_DIR>>. 475 476B<Arguments> 477 478See the L<HTTP Request Handler Skeleton|docs::2.0::user::handlers::http/HTTP_Request_Handler_Skeleton> for a description of handler arguments. 479 480B<Return> 481 482See L<Stacked Handlers|docs::2.0::user::handlers::intro/Stacked_Handlers> 483for a description of handler return codes. 484 485B<Examples> 486 487This phase is very similar to 488C<L<PerlPostReadRequestHandler|/PerlPostReadRequestHandler>>, with the 489only difference that it's run after the request has been mapped to the 490resource. Both phases are useful for doing something once per request, 491as early as possible. And usually you can take any 492C<L<PerlPostReadRequestHandler|/PerlPostReadRequestHandler>> and turn 493it into C<L<PerlHeaderParserHandler|/PerlHeaderParserHandler>> by 494simply changing the directive name in I<httpd.conf> and moving it 495inside the container where it should be executed. Moreover, because of 496this similarity mod_perl provides a special directive 497C<L<PerlInitHandler|/PerlInitHandler>> which if found outside resource 498containers behaves as 499C<L<PerlPostReadRequestHandler|/PerlPostReadRequestHandler>>, 500otherwise as C<L<PerlHeaderParserHandler|/PerlHeaderParserHandler>>. 501 502You already know that Apache handles the C<HEAD>, C<GET>, C<POST> and 503several other HTTP methods. But did you know that you can invent your 504own HTTP method as long as there is a client that supports it. If you 505think of emails, they are very similar to HTTP messages: they have a 506set of headers and a body, sometimes a multi-part body. Therefore we 507can develop a handler that extends HTTP by adding a support for the 508C<EMAIL> method. We can enable this protocol extension and push the 509real content handler during the 510C<L<PerlHeaderParserHandler|/PerlHeaderParserHandler>> phase: 511 512 <Location /email> 513 PerlHeaderParserHandler MyApache2::SendEmail 514 </Location> 515 516and here is the C<MyApache2::SendEmail> handler: 517 518 #file:MyApache2/SendEmail.pm 519 #-------------------------- 520 package MyApache2::SendEmail; 521 522 use strict; 523 use warnings; 524 525 use Apache2::RequestRec (); 526 use Apache2::RequestIO (); 527 use Apache2::RequestUtil (); 528 use Apache2::ServerUtil (); 529 use Apache2::ServerRec (); 530 use Apache2::Process (); 531 use APR::Table (); 532 533 use Apache2::Const -compile => qw(DECLINED OK); 534 535 use constant METHOD => 'EMAIL'; 536 use constant SMTP_HOSTNAME => "localhost"; 537 538 sub handler { 539 my $r = shift; 540 541 return Apache2::Const::DECLINED unless $r->method eq METHOD; 542 543 $r->server->method_register(METHOD); 544 $r->handler("perl-script"); 545 $r->push_handlers(PerlResponseHandler => \&send_email_handler); 546 547 return Apache2::Const::OK; 548 } 549 550 sub send_email_handler { 551 my $r = shift; 552 553 my %headers = map {$_ => $r->headers_in->get($_)} 554 qw(To From Subject); 555 556 my $content = content($r); 557 558 my $status = send_email(\%headers, \$content); 559 560 $r->content_type('text/plain'); 561 $r->print($status ? "ACK" : "NACK"); 562 return Apache2::Const::OK; 563 } 564 565 sub send_email { 566 my ($rh_headers, $r_body) = @_; 567 568 require MIME::Lite; 569 MIME::Lite->send("smtp", SMTP_HOSTNAME, Timeout => 60); 570 571 my $msg = MIME::Lite->new(%$rh_headers, Data => $$r_body); 572 #warn $msg->as_string; 573 $msg->send; 574 } 575 576 use APR::Brigade (); 577 use APR::Bucket (); 578 579 use Apache2::Const -compile => qw(MODE_READBYTES); 580 use APR::Const -compile => qw(SUCCESS BLOCK_READ); 581 582 use constant IOBUFSIZE => 8192; 583 584 sub content { 585 my $r = shift; 586 587 my $bb = APR::Brigade->new($r->pool, $r->connection->bucket_alloc); 588 589 my $data = ''; 590 my $seen_eos = 0; 591 do { 592 $r->input_filters->get_brigade($bb, 593 Apache2::Const::MODE_READBYTES, 594 APR::Const::BLOCK_READ, IOBUFSIZE); 595 596 for (my $b = $bb->first; $b; $b = $bb->next($b)) { 597 if ($b->is_eos) { 598 $seen_eos++; 599 last; 600 } 601 602 if ($b->read(my $buf)) { 603 $data .= $buf; 604 } 605 606 $b->remove; # optimization to reuse memory 607 } 608 } while (!$seen_eos); 609 610 $bb->destroy; 611 612 return $data; 613 } 614 615 1; 616 617Let's get the less interesting code out of the way. The function 618content() grabs the request body. The function send_email() sends the 619email over SMTP. You should adjust the constant C<SMTP_HOSTNAME> to 620point to your outgoing SMTP server. You can replace this function with 621your own if you prefer to use a different method to send email. 622 623Now to the more interesting functions. The function C<handler()> 624returns immediately and passes the control to the next handler if the 625request method is not equal to C<EMAIL> (set in the C<METHOD> 626constant): 627 628 return Apache2::Const::DECLINED unless $r->method eq METHOD; 629 630Next it tells Apache that this new method is a valid one and that the 631C<perl-script> handler will do the processing. 632 633 $r->server->method_register(METHOD); 634 $r->handler("perl-script"); 635 636Finally it pushes the function C<send_email_handler()> to the 637C<PerlResponseHandler> list of handlers: 638 639 $r->push_handlers(PerlResponseHandler => \&send_email_handler); 640 641The function terminates the header_parser phase by: 642 643 return Apache2::Const::OK; 644 645All other phases run as usual, so you can reuse any HTTP protocol 646hooks, such as authentication and fixup phases. 647 648When the response phase starts C<send_email_handler()> is invoked, 649assuming that no other response handlers were inserted before it. The 650response handler consists of three parts. Retrieve the email headers 651C<To>, C<From> and C<Subject>, and the body of the message: 652 653 my %headers = map {$_ => $r->headers_in->get($_)} 654 qw(To From Subject); 655 my $content = $r->content; 656 657Then send the email: 658 659 my $status = send_email(\%headers, \$content); 660 661Finally return to the client a simple response acknowledging that 662email has been sent and finish the response phase by returning 663C<Apache2::Const::OK>: 664 665 $r->content_type('text/plain'); 666 $r->print($status ? "ACK" : "NACK"); 667 return Apache2::Const::OK; 668 669Of course you will want to add extra validations if you want to use 670this code in production. This is just a proof of concept 671implementation. 672 673As already mentioned when you extend an HTTP protocol you need to have 674a client that knows how to use the extension. So here is a simple 675client that uses C<LWP::UserAgent> to issue an C<EMAIL> method request 676over HTTP protocol: 677 678 #file:send_http_email.pl 679 #----------------------- 680 #!/usr/bin/perl 681 682 use strict; 683 use warnings; 684 685 require LWP::UserAgent; 686 687 my $url = "http://localhost:8000/email/"; 688 689 my %headers = ( 690 From => 'example@example.com', 691 To => 'example@example.com', 692 Subject => '3 weeks in Tibet', 693 ); 694 695 my $content = <<EOI; 696 I didn't have an email software, 697 but could use HTTP so I'm sending it over HTTP 698 EOI 699 700 my $headers = HTTP::Headers->new(%headers); 701 my $req = HTTP::Request->new("EMAIL", $url, $headers, $content); 702 my $res = LWP::UserAgent->new->request($req); 703 print $res->is_success ? $res->content : "failed"; 704 705most of the code is just a custom data. The code that does something 706consists of four lines at the very end. Create C<HTTP::Headers> and 707C<HTTP::Request> object. Issue the request and get the 708response. Finally print the response's content if it was successful or 709just I<"failed"> if not. 710 711Now save the client code in the file I<send_http_email.pl>, adjust the 712I<To> field, make the file executable and execute it, after you have 713restarted the server. You should receive an email shortly to the 714address set in the I<To> field. 715 716 717 718 719 720=head2 PerlInitHandler 721 722When configured inside any container directive, except 723C<E<lt>VirtualHostE<gt>>, this handler is an alias for 724C<L<PerlHeaderParserHandler|/PerlHeaderParserHandler>> described 725earlier. Otherwise it acts as an alias for 726C<L<PerlPostReadRequestHandler|/PerlPostReadRequestHandler>> described 727earlier. 728 729It is the first handler to be invoked when serving a request. 730 731This phase is of type 732C<L<RUN_ALL|docs::2.0::user::handlers::intro/item_RUN_ALL>>. 733 734B<Arguments> 735 736See the L<HTTP Request Handler Skeleton|docs::2.0::user::handlers::http/HTTP_Request_Handler_Skeleton> for a description of handler arguments. 737 738B<Return> 739 740See L<Stacked Handlers|docs::2.0::user::handlers::intro/Stacked_Handlers> 741for a description of handler return codes. 742 743B<Examples> 744 745The best example here would be to use 746C<L<Apache2::Reload|docs::2.0::api::Apache2::Reload>> which takes the 747benefit of this directive. Usually 748C<L<Apache2::Reload|docs::2.0::api::Apache2::Reload>> is configured 749as: 750 751 PerlInitHandler Apache2::Reload 752 PerlSetVar ReloadAll Off 753 PerlSetVar ReloadModules "MyApache2::*" 754 755which during the current HTTP request will monitor and reload all 756C<MyApache2::*> modules that have been modified since the last HTTP 757request. However if we move the global configuration into a 758C<E<lt>LocationE<gt>> container: 759 760 <Location /devel> 761 PerlInitHandler Apache2::Reload 762 PerlSetVar ReloadAll Off 763 PerlSetVar ReloadModules "MyApache2::*" 764 SetHandler perl-script 765 PerlResponseHandler ModPerl::Registry 766 Options +ExecCGI 767 </Location> 768 769C<L<Apache2::Reload|docs::2.0::api::Apache2::Reload>> will reload the 770modified modules, only when a request to the I</devel> namespace is 771issued, because C<L<PerlInitHandler|/PerlInitHandler>> plays the role 772of C<L<PerlHeaderParserHandler|/PerlHeaderParserHandler>> here. 773 774 775 776 777 778=head2 PerlAccessHandler 779 780The I<access_checker> phase is the first of three handlers that are 781involved in what's known as AAA: Authentication, Authorization, and 782Access control. 783 784This phase can be used to restrict access from a certain IP address, 785time of the day or any other rule not connected to the user's 786identity. 787 788This phase is of type 789C<L<RUN_ALL|docs::2.0::user::handlers::intro/item_RUN_ALL>>. 790 791The handler's configuration scope is 792C<L<DIR|docs::2.0::user::config::config/item_DIR>>. 793 794B<Arguments> 795 796See the L<HTTP Request Handler Skeleton|docs::2.0::user::handlers::http/HTTP_Request_Handler_Skeleton> for a description of handler arguments. 797 798B<Return> 799 800See L<Stacked Handlers|docs::2.0::user::handlers::intro/Stacked_Handlers> 801for a description of handler return codes. 802 803B<Examples> 804 805The concept behind access checker handler is very simple, return 806C<Apache2::Const::FORBIDDEN> if the access is not allowed, otherwise 807return C<Apache2::Const::OK>. 808 809The following example handler denies requests made from IPs on the 810blacklist. 811 812 813 #file:MyApache2/BlockByIP.pm 814 #-------------------------- 815 package MyApache2::BlockByIP; 816 817 use strict; 818 use warnings; 819 820 use Apache2::RequestRec (); 821 use Apache2::Connection (); 822 823 use Apache2::Const -compile => qw(FORBIDDEN OK); 824 825 my %bad_ips = map {$_ => 1} qw(127.0.0.1 10.0.0.4); 826 827 sub handler { 828 my $r = shift; 829 830 return exists $bad_ips{$r->connection->remote_ip} 831 ? Apache2::Const::FORBIDDEN 832 : Apache2::Const::OK; 833 } 834 835 1; 836 837The handler retrieves the connection's IP address, looks it up in the 838hash of blacklisted IPs and forbids the access if found. If the IP is 839not blacklisted, the handler returns control to the next access 840checker handler, which may still block the access based on a different 841rule. 842 843To enable the handler simply add it to the container that needs to be 844protected. For example to protect an access to the registry scripts 845executed from the base location I</perl> add: 846 847 <Location /perl/> 848 SetHandler perl-script 849 PerlResponseHandler ModPerl::Registry 850 PerlAccessHandler MyApache2::BlockByIP 851 Options +ExecCGI 852 </Location> 853 854It's important to notice that C<PerlAccessHandler> can be configured 855for any subsection of the site, no matter whether it's served by a 856mod_perl response handler or not. For example to run the handler from 857our example for all requests to the server simply add to 858I<httpd.conf>: 859 860 <Location /> 861 PerlAccessHandler MyApache2::BlockByIP 862 </Location> 863 864 865 866 867 868 869=head2 PerlAuthenHandler 870 871The I<check_user_id> (I<authen>) phase is called whenever the 872requested file or directory is password protected. This, in turn, 873requires that the directory be associated with C<AuthName>, 874C<AuthType> and at least one C<require> directive. 875 876This phase is usually used to verify a user's identification 877credentials. If the credentials are verified to be correct, the 878handler should return C<Apache2::Const::OK>. Otherwise the handler 879returns C<Apache2::Const::HTTP_UNAUTHORIZED> to indicate that the user 880has not authenticated successfully. When Apache sends the HTTP header 881with this code, the browser will normally pop up a dialog box that 882prompts the user for login information. 883 884This phase is of type 885C<L<RUN_FIRST|docs::2.0::user::handlers::intro/item_RUN_FIRST>>. 886 887The handler's configuration scope is 888C<L<DIR|docs::2.0::user::config::config/item_DIR>>. 889 890B<Arguments> 891 892See the L<HTTP Request Handler Skeleton|docs::2.0::user::handlers::http/HTTP_Request_Handler_Skeleton> for a description of handler arguments. 893 894B<Return> 895 896See L<Stacked Handlers|docs::2.0::user::handlers::intro/Stacked_Handlers> 897for a description of handler return codes. 898 899B<Examples> 900 901The following handler authenticates users by asking for a username and 902a password and lets them in only if the length of a string made from 903the supplied username and password and a single space equals to the 904secret length, specified by the constant C<SECRET_LENGTH>. 905 906 #file:MyApache2/SecretLengthAuth.pm 907 #--------------------------------- 908 package MyApache2::SecretLengthAuth; 909 910 use strict; 911 use warnings; 912 913 use Apache2::Access (); 914 use Apache2::RequestUtil (); 915 916 use Apache2::Const -compile => qw(OK DECLINED HTTP_UNAUTHORIZED); 917 918 use constant SECRET_LENGTH => 14; 919 920 sub handler { 921 my $r = shift; 922 923 my ($status, $password) = $r->get_basic_auth_pw; 924 return $status unless $status == Apache2::Const::OK; 925 926 return Apache2::Const::OK 927 if SECRET_LENGTH == length join " ", $r->user, $password; 928 929 $r->note_basic_auth_failure; 930 return Apache2::Const::HTTP_UNAUTHORIZED; 931 } 932 933 1; 934 935First the handler retrieves the status of the authentication and the 936password in plain text. The status will be set to 937C<Apache2::Const::OK> only when the user has supplied the username and 938the password credentials. If the status is different, we just let 939Apache handle this situation for us, which will usually challenge the 940client so it'll supply the credentials. 941 942Note that C<get_basic_auth_pw()> does a few things behind the scenes, 943which are important to understand if you plan on implementing your own 944authentication mechanism that does not use C<get_basic_auth_pw()>. 945First, is checks the value of the configured C<AuthType> for the 946request, making sure it is C<Basic>. Then it makes sure that the 947Authorization (or Proxy-Authorization) header is formatted for 948C<Basic> authentication. Finally, after isolating the user and 949password from the header, it populates the I<ap_auth_type> slot in the 950request record with C<Basic>. For the first and last parts of this 951process, mod_perl offers an API. C<$r-E<gt>auth_type> returns the 952configured authentication type for the current request - whatever was 953set via the C<AuthType> configuration directive. 954C<$r-E<gt>ap_auth_type> populates the I<ap_auth_type> slot in the 955request record, which should be done after it has been confirmed that 956the request is indeed using C<Basic> authentication. (Note: 957C<$r-E<gt>ap_auth_type> was C<$r-E<gt>connection-E<gt>auth_type> in 958the mod_perl 1.0 API.) 959 960Once we know that we have the username and the password supplied by 961the client, we can proceed with the authentication. Our authentication 962algorithm is unusual. Instead of validating the username/password pair 963against a password file, we simply check that the string built from 964these two items plus a single space is C<SECRET_LENGTH> long (14 in 965our example). So for example the pair I<mod_perl/rules> authenticates 966correctly, whereas I<secret/password> does not, because the latter 967pair will make a string of 15 characters. Of course this is not a 968strong authentication scheme and you shouldn't use it for serious 969things, but it's fun to play with. Most authentication validations 970simply verify the username/password against a database of valid pairs, 971usually this requires the password to be encrypted first, since 972storing passwords in clear is a bad idea. 973 974Finally if our authentication fails the handler calls 975note_basic_auth_failure() and returns 976C<Apache2::Const::HTTP_UNAUTHORIZED>, which sets the proper HTTP 977response headers that tell the client that its user that the 978authentication has failed and the credentials should be supplied 979again. 980 981It's not enough to enable this handler for the authentication to 982work. You have to tell Apache what authentication scheme to use 983(C<Basic> or C<Digest>), which is specified by the C<AuthType> 984directive, and you should also supply the C<AuthName> -- the 985authentication realm, which is really just a string that the client 986usually uses as a title in the pop-up box, where the username and the 987password are inserted. Finally the C<Require> directive is needed to 988specify which usernames are allowed to authenticate. If you set it to 989C<valid-user> any username will do. 990 991Here is the whole configuration section that requires users to 992authenticate before they are allowed to run the registry scripts from 993I</perl/>: 994 995 <Location /perl/> 996 SetHandler perl-script 997 PerlResponseHandler ModPerl::Registry 998 PerlAuthenHandler MyApache2::SecretLengthAuth 999 Options +ExecCGI 1000 1001 AuthType Basic 1002 AuthName "The Gate" 1003 Require valid-user 1004 </Location> 1005 1006Just like C<PerlAccessHandler> and other mod_perl handlers, 1007C<PerlAuthenHandler> can be configured for any subsection of the site, 1008no matter whether it's served by a mod_perl response handler or 1009not. For example to use the authentication handler from the last 1010example for any requests to the site, simply use: 1011 1012 <Location /> 1013 PerlAuthenHandler MyApache2::SecretLengthAuth 1014 AuthType Basic 1015 AuthName "The Gate" 1016 Require valid-user 1017 </Location> 1018 1019 1020 1021 1022 1023 1024 1025=head2 PerlAuthzHandler 1026 1027The I<auth_checker> (I<authz>) phase is used for authorization 1028control. This phase requires a successful authentication from the 1029previous phase, because a username is needed in order to decide 1030whether a user is authorized to access the requested resource. 1031 1032As this phase is tightly connected to the authentication phase, the 1033handlers registered for this phase are only called when the requested 1034resource is password protected, similar to the auth phase. The handler 1035is expected to return C<Apache2::Const::DECLINED> to defer the 1036decision, C<Apache2::Const::OK> to indicate its acceptance of the 1037user's authorization, or C<Apache2::Const::HTTP_UNAUTHORIZED> to 1038indicate that the user is not authorized to access the requested 1039document. 1040 1041This phase is of type 1042C<L<RUN_FIRST|docs::2.0::user::handlers::intro/item_RUN_FIRST>>. 1043 1044The handler's configuration scope is 1045C<L<DIR|docs::2.0::user::config::config/item_DIR>>. 1046 1047B<Arguments> 1048 1049See the L<HTTP Request Handler Skeleton|docs::2.0::user::handlers::http/HTTP_Request_Handler_Skeleton> for a description of handler arguments. 1050 1051B<Return> 1052 1053See L<Stacked Handlers|docs::2.0::user::handlers::intro/Stacked_Handlers> 1054for a description of handler return codes. 1055 1056B<Examples> 1057 1058Here is the C<MyApache2::SecretResourceAuthz> handler which grants 1059access to certain resources only to certain users who have already 1060properly authenticated: 1061 1062 #file:MyApache2/SecretResourceAuthz.pm 1063 #------------------------------------ 1064 package MyApache2::SecretResourceAuthz; 1065 1066 use strict; 1067 use warnings; 1068 1069 use Apache2::Access (); 1070 use Apache2::RequestUtil (); 1071 1072 use Apache2::Const -compile => qw(OK HTTP_UNAUTHORIZED); 1073 1074 my %protected = ( 1075 'admin' => ['stas'], 1076 'report' => [qw(stas boss)], 1077 ); 1078 1079 sub handler { 1080 my $r = shift; 1081 1082 my $user = $r->user; 1083 if ($user) { 1084 my ($section) = $r->uri =~ m|^/company/(\w+)/|; 1085 if (defined $section && exists $protected{$section}) { 1086 my $users = $protected{$section}; 1087 return Apache2::Const::OK if grep { $_ eq $user } @$users; 1088 } 1089 else { 1090 return Apache2::Const::OK; 1091 } 1092 } 1093 1094 $r->note_basic_auth_failure; 1095 return Apache2::Const::HTTP_UNAUTHORIZED; 1096 } 1097 1098 1; 1099 1100This authorization handler is very similar to the authentication 1101handler L<from the previous section|/PerlAuthenHandler>. Here we rely 1102on the previous phase to get users authenticated, and now as we have 1103the username we can make decisions whether to let the user access the 1104resource it has asked for or not. In our example we have a simple hash 1105which maps which users are allowed to access what resources. So for 1106example anything under I</company/admin/> can be accessed only by the 1107user I<stas>, I</company/report/> can be accessed by users I<stas> and 1108I<boss>, whereas any other resources under I</company/> can be 1109accessed by everybody who has reached so far. If for some reason we 1110don't get the username, we or the user is not authorized to access the 1111resource the handler does the same thing as it does when the 1112authentication fails, i.e, calls: 1113 1114 $r->note_basic_auth_failure; 1115 return Apache2::Const::HTTP_UNAUTHORIZED; 1116 1117The configuration is similar to the one in L<the previous 1118section|/PerlAuthenHandler>, this time we just add the 1119C<PerlAuthzHandler> setting. The rest doesn't change. 1120 1121 Alias /company/ /home/httpd/httpd-2.0/perl/ 1122 <Location /company/> 1123 SetHandler perl-script 1124 PerlResponseHandler ModPerl::Registry 1125 PerlAuthenHandler MyApache2::SecretLengthAuth 1126 PerlAuthzHandler MyApache2::SecretResourceAuthz 1127 Options +ExecCGI 1128 1129 AuthType Basic 1130 AuthName "The Secret Gate" 1131 Require valid-user 1132 </Location> 1133 1134And if you want to run the authentication and authorization for the 1135whole site, simply add: 1136 1137 <Location /> 1138 PerlAuthenHandler MyApache2::SecretLengthAuth 1139 PerlAuthzHandler MyApache2::SecretResourceAuthz 1140 AuthType Basic 1141 AuthName "The Secret Gate" 1142 Require valid-user 1143 </Location> 1144 1145 1146 1147=head2 PerlTypeHandler 1148 1149The I<type_checker> phase is used to set the response MIME type 1150(C<Content-type>) and sometimes other bits of document type 1151information like the document language. 1152 1153For example C<mod_autoindex>, which performs automatic directory 1154indexing, uses this phase to map the filename extensions to the 1155corresponding icons which will be later used in the listing of files. 1156 1157Of course later phases may override the mime type set in this phase. 1158 1159This phase is of type 1160C<L<RUN_FIRST|docs::2.0::user::handlers::intro/item_RUN_FIRST>>. 1161 1162The handler's configuration scope is 1163C<L<DIR|docs::2.0::user::config::config/item_DIR>>. 1164 1165B<Arguments> 1166 1167See the L<HTTP Request Handler Skeleton|docs::2.0::user::handlers::http/HTTP_Request_Handler_Skeleton> for a description of handler arguments. 1168 1169B<Return> 1170 1171See L<Stacked Handlers|docs::2.0::user::handlers::intro/Stacked_Handlers> 1172for a description of handler return codes. 1173 1174B<Examples> 1175 1176The most important thing to remember when overriding the default 1177I<type_checker> handler, which is usually the mod_mime handler, is 1178that you have to set the handler that will take care of the response 1179phase and the response callback function or the code won't 1180work. mod_mime does that based on C<SetHandler> and C<AddHandler> 1181directives, and file extensions. So if you want the content handler to 1182be run by mod_perl, set either: 1183 1184 $r->handler('perl-script'); 1185 $r->set_handlers(PerlResponseHandler => \&handler); 1186 1187or: 1188 1189 $r->handler('modperl'); 1190 $r->set_handlers(PerlResponseHandler => \&handler); 1191 1192depending on which type of response handler is wanted. 1193 1194Writing a C<PerlTypeHandler> handler which sets the content-type value 1195and returns C<Apache2::Const::DECLINED> so that the default handler 1196will do the rest of the work, is not a good idea, because mod_mime 1197will probably override this and other settings. 1198 1199Therefore it's the easiest to leave this stage alone and do any 1200desired settings in the I<fixups> phase. 1201 1202 1203 1204 1205=head2 PerlFixupHandler 1206 1207The I<fixups> phase is happening just before the content handling 1208phase. It gives the last chance to do things before the response is 1209generated. For example in this phase C<mod_env> populates the 1210environment with variables configured with I<SetEnv> and I<PassEnv> 1211directives. 1212 1213This phase is of type 1214C<L<RUN_ALL|docs::2.0::user::handlers::intro/item_RUN_ALL>>. 1215 1216The handler's configuration scope is 1217C<L<DIR|docs::2.0::user::config::config/item_DIR>>. 1218 1219B<Arguments> 1220 1221See the L<HTTP Request Handler Skeleton|docs::2.0::user::handlers::http/HTTP_Request_Handler_Skeleton> for a description of handler arguments. 1222 1223B<Return> 1224 1225See L<Stacked Handlers|docs::2.0::user::handlers::intro/Stacked_Handlers> 1226for a description of handler return codes. 1227 1228B<Examples> 1229 1230The following fixup handler example tells Apache at run time which 1231handler and callback should be used to process the request based on 1232the file extension of the request's URI. 1233 1234 #file:MyApache2/FileExtDispatch.pm 1235 #-------------------------------- 1236 package MyApache2::FileExtDispatch; 1237 1238 use strict; 1239 use warnings; 1240 1241 use Apache2::RequestIO (); 1242 use Apache2::RequestRec (); 1243 use Apache2::RequestUtil (); 1244 1245 use Apache2::Const -compile => 'OK'; 1246 1247 use constant HANDLER => 0; 1248 use constant CALLBACK => 1; 1249 1250 my %exts = ( 1251 cgi => ['perl-script', \&cgi_handler], 1252 pl => ['modperl', \&pl_handler ], 1253 tt => ['perl-script', \&tt_handler ], 1254 txt => ['default-handler', undef ], 1255 ); 1256 1257 sub handler { 1258 my $r = shift; 1259 1260 my ($ext) = $r->uri =~ /\.(\w+)$/; 1261 $ext = 'txt' unless defined $ext and exists $exts{$ext}; 1262 1263 $r->handler($exts{$ext}->[HANDLER]); 1264 1265 if (defined $exts{$ext}->[CALLBACK]) { 1266 $r->set_handlers(PerlResponseHandler => $exts{$ext}->[CALLBACK]); 1267 } 1268 1269 return Apache2::Const::OK; 1270 } 1271 1272 sub cgi_handler { content_handler($_[0], 'cgi') } 1273 sub pl_handler { content_handler($_[0], 'pl') } 1274 sub tt_handler { content_handler($_[0], 'tt') } 1275 1276 sub content_handler { 1277 my ($r, $type) = @_; 1278 1279 $r->content_type('text/plain'); 1280 $r->print("A handler of type '$type' was called"); 1281 1282 return Apache2::Const::OK; 1283 } 1284 1285 1; 1286 1287In the example we have used the following mapping. 1288 1289 my %exts = ( 1290 cgi => ['perl-script', \&cgi_handler], 1291 pl => ['modperl', \&pl_handler ], 1292 tt => ['perl-script', \&tt_handler ], 1293 txt => ['default-handler', undef ], 1294 ); 1295 1296So that I<.cgi> requests will be handled by the C<perl-script> handler 1297and the C<cgi_handler()> callback, I<.pl> requests by C<modperl> and 1298C<pl_handler()>, I<.tt> (template toolkit) by C<perl-script> and the 1299C<tt_handler()>, finally I<.txt> request by the C<default-handler> 1300handler, which requires no callback. 1301 1302Moreover the handler assumes that if the request's URI has no file 1303extension or it does, but it's not in its mapping, the 1304C<default-handler> will be used, as if the I<txt> extension was used. 1305 1306After doing the mapping, the handler assigns the handler: 1307 1308 $r->handler($exts{$ext}->[HANDLER]); 1309 1310and the callback if needed: 1311 1312 if (defined $exts{$ext}->[CALLBACK]) { 1313 $r->set_handlers( 1314 PerlResponseHandler => $exts{$ext}->[CALLBACK]); 1315 } 1316 1317In this simple example the callback functions don't do much but 1318calling the same content handler which simply prints the name of the 1319extension if handled by mod_perl, otherwise Apache will serve the 1320other files using the default handler. In real world you will use 1321callbacks to real content handlers that do real things. 1322 1323Here is how this handler is configured: 1324 1325 Alias /dispatch/ /home/httpd/httpd-2.0/htdocs/ 1326 <Location /dispatch/> 1327 PerlFixupHandler MyApache2::FileExtDispatch 1328 </Location> 1329 1330Notice that there is no need to specify anything, but the fixup 1331handler. It applies the rest of the settings dynamically at run-time. 1332 1333 1334 1335 1336 1337 1338=head2 PerlResponseHandler 1339 1340The I<handler> (I<response>) phase is used for generating the 1341response. This is arguably the most important phase and most of the 1342existing Apache modules do most of their work at this phase. 1343 1344This is the only phase that requires two directives under 1345mod_perl. For example: 1346 1347 <Location /perl> 1348 SetHandler perl-script 1349 PerlResponseHandler MyApache2::WorldDomination 1350 </Location> 1351 1352C<SetHandler> set to 1353C<L<perl-script|docs::2.0::user::config::config/C_perl_script_>> or 1354C<L<modperl|docs::2.0::user::config::config/C_modperl_>> tells Apache 1355that mod_perl is going to handle the response 1356generation. C<PerlResponseHandler> tells mod_perl which callback is 1357going to do the job. 1358 1359This phase is of type 1360C<L<RUN_FIRST|docs::2.0::user::handlers::intro/item_RUN_FIRST>>. 1361 1362The handler's configuration scope is 1363C<L<DIR|docs::2.0::user::config::config/item_DIR>>. 1364 1365B<Arguments> 1366 1367See the L<HTTP Request Handler Skeleton|docs::2.0::user::handlers::http/HTTP_Request_Handler_Skeleton> for a description of handler arguments. 1368 1369B<Return> 1370 1371See L<Stacked Handlers|docs::2.0::user::handlers::intro/Stacked_Handlers> 1372for a description of handler return codes. 1373 1374B<Examples> 1375 1376Most of the C<Apache::> modules on CPAN are dealing with this 1377phase. In fact most of the developers spend the majority of their time 1378working on handlers that generate response content. 1379 1380Let's write a simple response handler, that just generates some 1381content. This time let's do something more interesting than printing 1382I<"Hello world">. Let's write a handler that prints itself: 1383 1384 #file:MyApache2/Deparse.pm 1385 #------------------------ 1386 package MyApache2::Deparse; 1387 1388 use strict; 1389 use warnings; 1390 1391 use Apache2::RequestRec (); 1392 use Apache2::RequestIO (); 1393 use B::Deparse (); 1394 1395 use Apache2::Const -compile => 'OK'; 1396 1397 sub handler { 1398 my $r = shift; 1399 1400 $r->content_type('text/plain'); 1401 $r->print('sub handler ', B::Deparse->new->coderef2text(\&handler)); 1402 1403 return Apache2::Const::OK; 1404 } 1405 1; 1406 1407To enable this handler add to I<httpd.conf>: 1408 1409 <Location /deparse> 1410 SetHandler modperl 1411 PerlResponseHandler MyApache2::Deparse 1412 </Location> 1413 1414Now when the server is restarted and we issue a request to 1415I<http://localhost/deparse> we get the following response: 1416 1417 sub handler { 1418 package MyApache2::Deparse; 1419 use warnings; 1420 use strict 'refs'; 1421 my $r = shift @_; 1422 $r->content_type('text/plain'); 1423 $r->print('sub handler ', 'B::Deparse'->new->coderef2text(\&handler)); 1424 return 0; 1425 } 1426 1427If you compare it to the source code, it's pretty much the same 1428code. C<B::Deparse> is fun to play with! 1429 1430 1431 1432 1433 1434 1435 1436=head2 PerlLogHandler 1437 1438The I<log_transaction> phase happens no matter how the previous phases 1439have ended up. If one of the earlier phases has aborted a request, 1440e.g., failed authentication or 404 (file not found) errors, the rest of 1441the phases up to and including the response phases are skipped. But 1442this phase is always executed. 1443 1444By this phase all the information about the request and the response 1445is known, therefore the logging handlers usually record this 1446information in various ways (e.g., logging to a flat file or a 1447database). 1448 1449This phase is of type 1450C<L<RUN_ALL|docs::2.0::user::handlers::intro/item_RUN_ALL>>. 1451 1452The handler's configuration scope is 1453C<L<DIR|docs::2.0::user::config::config/item_DIR>>. 1454 1455B<Arguments> 1456 1457See the L<HTTP Request Handler Skeleton|docs::2.0::user::handlers::http/HTTP_Request_Handler_Skeleton> for a description of handler arguments. 1458 1459B<Return> 1460 1461See L<Stacked Handlers|docs::2.0::user::handlers::intro/Stacked_Handlers> 1462for a description of handler return codes. 1463 1464B<Examples> 1465 1466Imagine a situation where you have to log requests into individual 1467files, one per user. Assuming that all requests start with 1468I</~username/>, so it's easy to categorize requests by the 1469username. Here is the log handler that does that: 1470 1471 #file:MyApache2/LogPerUser.pm 1472 #--------------------------- 1473 package MyApache2::LogPerUser; 1474 1475 use strict; 1476 use warnings; 1477 1478 use Apache2::RequestRec (); 1479 use Apache2::Connection (); 1480 1481 use Fcntl qw(:flock); 1482 use File::Spec::Functions qw(catfile); 1483 1484 use Apache2::Const -compile => qw(OK DECLINED); 1485 1486 sub handler { 1487 my $r = shift; 1488 1489 my ($username) = $r->uri =~ m|^/~([^/]+)|; 1490 return Apache2::Const::DECLINED unless defined $username; 1491 1492 my $entry = sprintf qq(%s [%s] "%s" %d %d\n), 1493 $r->connection->remote_ip, scalar(localtime), 1494 $r->uri, $r->status, $r->bytes_sent; 1495 1496 my $log_path = catfile Apache2::ServerUtil::server_root, 1497 "logs", "$username.log"; 1498 open my $fh, ">>$log_path" or die "can't open $log_path: $!"; 1499 flock $fh, LOCK_EX; 1500 print $fh $entry; 1501 close $fh; 1502 1503 return Apache2::Const::OK; 1504 } 1505 1; 1506 1507First the handler tries to figure out what username the request is 1508issued for, if it fails to match the URI, it simply returns 1509C<Apache2::Const::DECLINED>, letting other log handlers to do the 1510logging. Though it could return C<Apache2::Const::OK> since all other 1511log handlers will be run anyway. 1512 1513Next it builds the log entry, similar to the default I<access_log> 1514entry. It's comprised of remote IP, the current time, the uri, the 1515return status and how many bytes were sent to the client as a response 1516body. 1517 1518Finally the handler appends this entry to the log file for the user 1519the request was issued for. Usually it's safe to append short strings 1520to the file without being afraid of messing up the file, when two 1521files attempt to write at the same time, but just to be on the safe 1522side the handler exclusively locks the file before performing the 1523writing. 1524 1525To configure the handler simply enable the module with the 1526C<PerlLogHandler> directive, for the desired URI namespace (starting 1527with : I</~> in our example): 1528 1529 <LocationMatch "^/~"> 1530 SetHandler perl-script 1531 PerlResponseHandler ModPerl::Registry 1532 PerlLogHandler MyApache2::LogPerUser 1533 Options +ExecCGI 1534 </LocationMatch> 1535 1536After restarting the server and issuing requests to the following 1537URIs: 1538 1539 http://localhost/~stas/test.pl 1540 http://localhost/~eric/test.pl 1541 http://localhost/~stas/date.pl 1542 1543The C<MyApache2::LogPerUser> handler will append to I<logs/stas.log>: 1544 1545 127.0.0.1 [Sat Aug 31 01:50:38 2002] "/~stas/test.pl" 200 8 1546 127.0.0.1 [Sat Aug 31 01:50:40 2002] "/~stas/date.pl" 200 44 1547 1548and to I<logs/eric.log>: 1549 1550 127.0.0.1 [Sat Aug 31 01:50:39 2002] "/~eric/test.pl" 200 8 1551 1552It's important to notice that C<PerlLogHandler> can be configured for 1553any subsection of the site, no matter whether it's served by a 1554mod_perl response handler or not. For example to run the handler from 1555our example for all requests to the server, simply add to 1556I<httpd.conf>: 1557 1558 <Location /> 1559 PerlLogHandler MyApache2::LogPerUser 1560 </Location> 1561 1562Since the C<PerlLogHandler> phase is of type 1563C<L<RUN_ALL|docs::2.0::user::handlers::intro/item_RUN_ALL>>, all other 1564logging handlers will be called as well. 1565 1566 1567 1568 1569 1570 1571 1572=head2 PerlCleanupHandler 1573 1574There is no I<cleanup> Apache phase, it exists only inside mod_perl. 1575It is used to execute some code immediately after the request has been 1576served (the client went away) and before the request object is 1577destroyed. 1578 1579There are several usages for this use phase. The obvious one is to run 1580a cleanup code, for example removing temporarily created files. The 1581less obvious is to use this phase instead of 1582C<L<PerlLogHandler|/PerlLogHandler>> if the logging operation is time 1583consuming. This approach allows to free the client as soon as the 1584response is sent. 1585 1586This phase is of type 1587C<L<RUN_ALL|docs::2.0::user::handlers::intro/item_RUN_ALL>>. 1588 1589The handler's configuration scope is 1590C<L<DIR|docs::2.0::user::config::config/item_DIR>>. 1591 1592B<Arguments> 1593 1594See the L<HTTP Request Handler Skeleton|docs::2.0::user::handlers::http/HTTP_Request_Handler_Skeleton> for a description of handler arguments. 1595 1596B<Return> 1597 1598See L<Stacked Handlers|docs::2.0::user::handlers::intro/Stacked_Handlers> 1599for a description of handler return codes. 1600 1601B<Examples> 1602 1603There are two ways to register and run cleanup handlers: 1604 1605=over 1606 1607=item 1 Using the C<PerlCleanupHandler> phase 1608 1609 PerlCleanupHandler MyApache2::Cleanup 1610 1611or: 1612 1613 $r->push_handlers(PerlCleanupHandler => \&cleanup); 1614 1615This method is identical to all other handlers. 1616 1617In this technique the C<cleanup()> callback accepts C<$r> as its only 1618argument. 1619 1620=item 2 Using C<cleanup_register()> acting on the request object's pool 1621 1622Since a request object pool is destroyed at the end of each request, 1623we can use 1624C<L<cleanup_register|docs::2.0::api::APR::Pool/C_cleanup_register_>> 1625to register a cleanup callback which will be executed just before the 1626pool is destroyed. For example: 1627 1628 $r->pool->cleanup_register(\&cleanup, $arg); 1629 1630The important difference from using the C<PerlCleanupHandler> handler, 1631is that here you can pass an optional arbitrary argument to the 1632callback function, and no C<$r> argument is passed by 1633default. Therefore if you need to pass any data other than C<$r> you 1634may want to use this technique. 1635 1636=back 1637 1638Here is an example where the cleanup handler is used to delete a 1639temporary file. The response handler is running C<ls -l> and stores 1640the output in temporary file, which is then used by 1641C<$r-E<gt>sendfile> to send the file's contents. We use 1642C<push_handlers()> to push C<PerlCleanupHandler> to unlink the file at 1643the end of the request. 1644 1645 #file:MyApache2/Cleanup1.pm 1646 #------------------------- 1647 package MyApache2::Cleanup1; 1648 1649 use strict; 1650 use warnings FATAL => 'all'; 1651 1652 use File::Spec::Functions qw(catfile); 1653 1654 use Apache2::RequestRec (); 1655 use Apache2::RequestIO (); 1656 use Apache2::RequestUtil (); 1657 1658 use Apache2::Const -compile => qw(OK DECLINED); 1659 use APR::Const -compile => 'SUCCESS'; 1660 1661 my $file = catfile "/tmp", "data"; 1662 1663 sub handler { 1664 my $r = shift; 1665 1666 $r->content_type('text/plain'); 1667 1668 local @ENV{qw(PATH BASH_ENV)}; 1669 qx(/bin/ls -l > $file); 1670 1671 my $status = $r->sendfile($file); 1672 die "sendfile has failed" unless $status == APR::Const::SUCCESS; 1673 1674 $r->push_handlers(PerlCleanupHandler => \&cleanup); 1675 1676 return Apache2::Const::OK; 1677 } 1678 1679 sub cleanup { 1680 my $r = shift; 1681 1682 die "Can't find file: $file" unless -e $file; 1683 unlink $file or die "failed to unlink $file"; 1684 1685 return Apache2::Const::OK; 1686 } 1687 1; 1688 1689Next we add the following configuration: 1690 1691 <Location /cleanup1> 1692 SetHandler modperl 1693 PerlResponseHandler MyApache2::Cleanup1 1694 </Location> 1695 1696Now when a request to I</cleanup1> is made, the contents of the 1697current directory will be printed and once the request is over the 1698temporary file is deleted. 1699 1700This response handler has a problem of running in a multi-process 1701environment, since it uses the same file, and several processes may 1702try to read/write/delete that file at the same time, wrecking 1703havoc. We could have appended the process id C<$$> to the file's name, 1704but remember that mod_perl 2.0 code may run in the threaded 1705environment, meaning that there will be many threads running in the 1706same process and the C<$$> trick won't work any longer. Therefore one 1707really has to use this code to create unique, but predictable, file 1708names across threads and processes: 1709 1710 sub unique_id { 1711 require Apache2::MPM; 1712 require APR::OS; 1713 return Apache2::MPM->is_threaded 1714 ? "$$." . ${ APR::OS::current_thread_id() } 1715 : $$; 1716 } 1717 1718In the threaded environment it will return a string containing the 1719process ID, followed by a thread ID. In the non-threaded environment 1720only the process ID will be returned. However since it gives us a 1721predictable string, they may still be a non-satisfactory 1722solution. Therefore we need to use a random string. We can either 1723either Perl's C<rand>, some CPAN module or the APR's C<APR::UUID>: 1724 1725 sub unique_id { 1726 require APR::UUID; 1727 return APR::UUID->new->format; 1728 } 1729 1730Now the problem is how do we tell the cleanup handler what file should 1731be cleaned up? We could have stored it in the C<$r-E<gt>notes> table 1732in the response handler and then retrieve it in the cleanup 1733handler. However there is a better way - as mentioned earlier, we can 1734register a callback for request pool cleanup, and when using this 1735method we can pass an arbitrary argument to it. Therefore in our case 1736we choose to pass the file name, based on random string. Here is a 1737better version of the response and cleanup handlers, that uses this 1738technique: 1739 1740 #file: MyApache2/Cleanup2.pm 1741 #------------------------- 1742 package MyApache2::Cleanup2; 1743 1744 use strict; 1745 use warnings FATAL => 'all'; 1746 1747 use File::Spec::Functions qw(catfile); 1748 1749 use Apache2::RequestRec (); 1750 use Apache2::RequestIO (); 1751 use Apache2::RequestUtil (); 1752 use APR::UUID (); 1753 use APR::Pool (); 1754 1755 use Apache2::Const -compile => qw(OK DECLINED); 1756 use APR::Const -compile => 'SUCCESS'; 1757 1758 my $file_base = catfile "/tmp", "data-"; 1759 1760 sub handler { 1761 my $r = shift; 1762 1763 $r->content_type('text/plain'); 1764 my $file = $file_base . APR::UUID->new->format; 1765 1766 local @ENV{qw(PATH BASH_ENV)}; 1767 qx(/bin/ls -l > $file); 1768 1769 my $status = $r->sendfile($file); 1770 die "sendfile has failed" unless $status == APR::Const::SUCCESS; 1771 1772 $r->pool->cleanup_register(\&cleanup, $file); 1773 1774 return Apache2::Const::OK; 1775 } 1776 1777 sub cleanup { 1778 my $file = shift; 1779 1780 die "Can't find file: $file" unless -e $file; 1781 unlink $file or die "failed to unlink $file"; 1782 1783 return Apache2::Const::OK; 1784 } 1785 1; 1786 1787Similarly to the first handler, we add the configuration: 1788 1789 <Location /cleanup2> 1790 SetHandler modperl 1791 PerlResponseHandler MyApache2::Cleanup2 1792 </Location> 1793 1794And now when requesting I</cleanup2> we still get the same output -- 1795the listing of the current directory -- but this time this code will 1796work correctly in the multi-processes/multi-threaded environment and 1797temporary files get cleaned up as well. 1798 1799 1800=head3 Possible Caveats 1801 1802C<PerlCleanupHandler> may fail to be completed on server 1803shutdown/graceful restart since Apache will kill the registered 1804handlers via SIGTERM, before they had a chance to run or even in the 1805middle of its execution. See: 1806http://marc.theaimsgroup.com/?t=106387845200003&r=1&w=2 1807http://marc.theaimsgroup.com/?l=apache-modperl-dev&m=106427616108596&w=2 1808 1809 1810 1811 1812 1813 1814 1815=head1 Miscellaneous Issues 1816 1817 1818=head2 Handling HEAD Requests 1819 1820In order to avoid the overhead of sending the data to the client when 1821the request is of type HEAD in mod_perl 1.0 we L<used to return 1822early|docs::1.0::guide::porting/Generating_correct_HTTP_Headers> from 1823the handler: 1824 1825 return Apache2::Const::OK if $r->header_only; 1826 1827This logic should not be used in mod_perl 2.0, because Apache 2.0 1828automatically discards the response body for HEAD requests. It expects 1829the full body to generate the correct set of response headers, if you 1830don't send the body you may encounter problems. 1831 1832(You can also read the comment in for C<ap_http_header_filter()> in 1833I<modules/http/http_protocol.c> in the Apache 2.0 source.) 1834 1835 1836 1837 1838 1839=head2 C<Content-Length> Response Header 1840 1841You may encounter some issues with the C-L (C<Content-Length>) 1842header. Some of them are discussed here. 1843 1844=over 1845 1846=item * The special case of C<Content-Length: 0> 1847 1848Since Apache proclaims itself governor of the C-L header via the C-L 1849filter (ap_content_length_filter at F<httpd-2.0/server/protocol.c>), 1850for the most part C<GET> and C<HEAD> behave exactly the same. 1851However, when Apache sees a C<HEAD> request with a C-L header of zero 1852it takes special action and removes the C-L header. This is done to 1853protect against handlers that called C<$r-E<gt>header_only> (L<which 1854was ok in 1.3 but is not in 2.0|/Handling_HEAD_Requests>). Therefore, 1855C<GET> and C<HEAD> behave identically, except when the content 1856handler (and/or filters) end up sending no content. For more details 1857refer to the lengthy comments in C<ap_http_header_filter()> in 1858F<httpd-2.0/modules/http/http_protocol.c>). 1859 1860For more discussion on why it is important to get HEAD requests right, 1861see these threads from the mod_perl list: 1862 1863 http://marc.theaimsgroup.com/?l=apache-modperl&m=108647669726915&w=2 1864 http://marc.theaimsgroup.com/?t=109122984600001&r=1&w=2 1865 1866as well as this bug report from mozilla, which shows how C<HEAD> 1867requests are used in the wild: 1868 1869 http://bugzilla.mozilla.org/show_bug.cgi?id=245447 1870 1871=item * Not getting C<Content-Length> header with C<HEAD> requests 1872 1873Even though the spec says that content handlers should send an 1874identical response for GET and HEAD requests, some folks try to 1875L<avoid the overhead of generating the response 1876body|/Handling_HEAD_Requests>, which Apache is going to discard anyway 1877for HEAD requests. The following discussion assumes that we deal with 1878a HEAD request. 1879 1880When Apache sees EOS and no headers and no response body were sent, 1881C<ap_content_length_filter()> (F<httpd-2.0/server/protocol.c>) sets 1882C-L to 0. Later on C<ap_http_header_filter()> 1883(F<httpd-2.0/modules/http/http_protocol.c>) removes the C-L header for 1884the HEAD requests. 1885 1886The workaround is to force the sending of the response headers, before 1887C<EOS> was sent (which happens when the response handler returns). The 1888simplest solution is to use rflush(): 1889 1890 if ($r->header_only) { # HEAD 1891 $body_len = calculate_body_len(); 1892 $r->set_content_length($body_len); 1893 $r->rflush; 1894 } 1895 else { # GET 1896 # generate and send the body 1897 } 1898 1899now if the handler sets the C-L header it'll be delivered to the 1900client unmodified. 1901 1902=back 1903 1904 1905 1906=head1 Misc Notes 1907 1908These items will need to be extended and integrated in this or other 1909HTTP related documents: 1910 1911=over 1912 1913=item * front-end back-end setup: mod_proxy+X-Forwarded-For 1914 1915apache-1.3: 1916 1917frontend: mod_proxy_add_forward http://develooper.com/code/mpaf/ 1918 1919backend: mod_rpaf (reverse proxy add forward): 1920http://stderr.net/apache/rpaf/ 1921 1922apache-2.x: 1923 1924frontend: mod_proxy 1925 1926backend: mod_rpaf: http://stderr.net/apache/rpaf/ 1927 1928=back 1929 1930 1931 1932=head1 Extending HTTP Protocol 1933 1934Extending HTTP under mod_perl is a trivial task. Look at L<the 1935example of adding a new method C<EMAIL>|/PerlHeaderParserHandler> for 1936details. 1937 1938 1939=head1 HTTP Status Codes 1940 1941The Hypertext Transfer Protocol (HTTP) is an application-level 1942protocol for distributed, collaborative, hypermedia information 1943systems. It is a generic, stateless, protocol which can be used for 1944many tasks beyond its use for hypertext, such as name servers and 1945distributed object management systems, through extension of its 1946request methods, error codes and headers. A feature of HTTP is the 1947typing and negotiation of data representation, allowing systems to be 1948built independently of the data being transferred. 1949 1950HTTP 1.0 is described in Requests For Comments (RFC) 1945. HTTP 1.1 is 1951the latest version of the specifications and as of this writing HTTP 19521.1 is covered in RFC 2616. 1953 1954When writing mod_perl applications, usually only a small subset of HTTP 1955response codes is used, but sometimes you need to know others as 1956well. We will give a short description of each code and you will find 1957the extended explanation in the appropriate RFC. (Section 9 in RFC 19581945 and section 10 in RFC 2616). You can always find the latest link 1959to these RFCs at the Web Consortium site, 1960I<http://www.w3.org/Protocols/>. 1961 1962While HTTP 1.1 is widely supported, HTTP 1.0 still remains the 1963mainstream standard. Therefore we will supply a summary of the both 1964versions including the corresponding Apache constants. 1965 1966In mod_perl these constants can be accessed the 1967C<L<Apache::Constants|docs::1.0::api::Apache::Constants>> 1968package (e.g., to access the HTTP_OK constant use 1969C<Apache::Constants::HTTP_OK>). See the 1970C<L<Apache::Constants|docs::1.0::api::Apache::Constants>> manpage 1971for more information. 1972 1973In mod_perl2 these constants can be accessed the 1974C<L<Apache2::Const|docs::2.0::api::Apache2::Const>> 1975package (e.g., to access the HTTP_OK constant use 1976C<Apache2::Const::HTTP_OK>). See the 1977C<L<Apache2::Const|docs::2.0::api::Apache2::Const>> manpage 1978for more information. 1979 1980=head2 HTTP 1.0 Status Codes 1981 1982=over 4 1983 1984=item * 1985 1986Successful 2xx: 1987 1988 200 HTTP_OK OK 1989 201 HTTP_CREATED Created 1990 202 HTTP_ACCEPTED Accepted 1991 204 HTTP_NO_CONTENT No Content 1992 1993=item * 1994 1995Redirection 3xx: 1996 1997 301 HTTP_MOVED_PERMANENTLY Multiple Choices 1998 302 HTTP_MOVED_TEMPORARILY Moved Permanently 1999 303 HTTP_SEE_OTHER Moved Temporarily 2000 304 HTTP_NOT_MODIFIED Not Modified 2001 2002=item * 2003 2004Client Error 4xx: 2005 2006 400 HTTP_BAD_REQUEST Bad Request 2007 401 HTTP_UNAUTHORIZED Unauthorized 2008 403 HTTP_FORBIDDEN Forbidden 2009 404 HTTP_NOT_FOUND Not Found 2010 2011=item * 2012 2013Server Error 5xx: 2014 2015 500 HTTP_INTERNAL_SERVER_ERROR Internal Server Error 2016 501 HTTP_NOT_IMPLEMENTED Not Implemented 2017 502 HTTP_BAD_GATEWAY Bad Gateway 2018 503 HTTP_SERVICE_UNAVAILABLE Service UnavailableStatus Codes 2019 2020=back 2021 2022=head2 HTTP 1.1 Status Codes 2023 2024=over 4 2025 2026=item * 2027 2028Informational 1xx: 2029 2030 100 HTTP_CONTINUE Continue 2031 101 HTTP_SWITCHING_PROTOCOLS Switching Protocols 2032 2033=item * 2034 2035Successful 2xx: 2036 2037 200 HTTP_OK OK 2038 201 HTTP_CREATED Created 2039 202 HTTP_ACCEPTED Accepted 2040 203 HTTP_NON_AUTHORITATIVE Non-Authoritative Information 2041 204 HTTP_NO_CONTENT No Content 2042 205 HTTP_RESET_CONTENT Reset Content 2043 206 HTTP_PARTIAL_CONTENT Partial Content 2044 2045=item * 2046 2047Redirection 3xx: 2048 2049 300 HTTP_MULTIPLE_CHOICES Multiple Choices 2050 301 HTTP_MOVED_PERMANENTLY Moved Permanently 2051 302 HTTP_MOVED_TEMPORARILY Found 2052 303 HTTP_SEE_OTHER See Other 2053 304 HTTP_NOT_MODIFIED Not Modified 2054 305 HTTP_USE_PROXY Use Proxy 2055 306 (Unused) 2056 307 HTTP_TEMPORARY_REDIRECT Temporary Redirect 2057 2058=item * 2059 2060Client Error 4xx: 2061 2062 400 HTTP_BAD_REQUEST Bad Request 2063 401 HTTP_UNAUTHORIZED Unauthorized 2064 402 HTTP_PAYMENT_REQUIRED Payment Required 2065 403 HTTP_FORBIDDEN Forbidden 2066 404 HTTP_NOT_FOUND Not Found 2067 405 HTTP_METHOD_NOT_ALLOWED Method Not Allowed 2068 406 HTTP_NOT_ACCEPTABLE Not Acceptable 2069 407 HTTP_PROXY_AUTHENTICATION_REQUIRED Proxy Authentication Required 2070 408 HTTP_REQUEST_TIMEOUT Request Timeout 2071 409 HTTP_CONFLICT Conflict 2072 410 HTTP_GONE Gone 2073 411 HTTP_LENGTH REQUIRED Length Required 2074 412 HTTP_PRECONDITION_FAILED Precondition Failed 2075 413 HTTP_REQUEST_ENTITY_TOO_LARGE Request Entity Too Large 2076 414 HTTP_REQUEST_URI_TOO_LARGE Request-URI Too Long 2077 415 HTTP_UNSUPPORTED_MEDIA_TYPE Unsupported Media Type 2078 416 HTTP_RANGE_NOT_SATISFIABLE Requested Range Not Satisfiable 2079 417 HTTP_EXPECTATION_FAILED Expectation Failed 2080 2081=item * 2082 2083Server Error 5xx: 2084 2085 500 HTTP_INTERNAL_SERVER_ERROR Internal Server Error 2086 501 HTTP_NOT IMPLEMENTED Not Implemented 2087 502 HTTP_BAD_GATEWAY Bad Gateway 2088 503 HTTP_SERVICE_UNAVAILABLE Service Unavailable 2089 504 HTTP_GATEWAY_TIME_OUT Gateway Timeout 2090 505 HTTP_VERSION_NOT_SUPPORTED HTTP Version Not Supported 2091 2092=back 2093 2094=head2 References 2095 2096All the information related to web protocols can be found at the World 2097Wide Web Consortium site, I<http://www.w3.org/Protocols/>. 2098 2099There are many mirrors of the RFCs all around the world. One of the 2100good starting points might be I<http://www.rfc-editor.org/>. 2101 2102The Eagle Book provided much of the HTTP constants material shown here 2103I<http://www.modperl.com/book/chapters/ch9.html#The_Apache_Constants_Class> 2104 2105=head1 Maintainers 2106 2107Maintainer is the person(s) you should contact with updates, 2108corrections and patches. 2109 2110=over 2111 2112=item * 2113 2114L<The mod_perl development team and numerous 2115contributors|about::contributors::people>. 2116 2117 2118=back 2119 2120 2121=head1 Authors 2122 2123=over 2124 2125=item * 2126 2127Stas Bekman [http://stason.org/] 2128 2129=back 2130 2131Only the major authors are listed above. For contributors see the 2132Changes file. 2133 2134 2135 2136=cut 2137 2138