mod perl 2.0 tutorial slides.pdf
TRANSCRIPT
![Page 1: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/1.jpg)
Tutorial Slides: mod_perl 2.0 By Example
by Stas Bekman http://stason.org/
OSCON US 2005Mon, August 1 2005
Portland, Oregon, USA
Stas BekmanTutorial Slides: mod_perl 2.0 By Example Slide 1
![Page 2: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/2.jpg)
This talk is available from:http://stason.org/talks/
Stas BekmanTutorial Slides: mod_perl 2.0 By Example Slide 2
![Page 3: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/3.jpg)
Stas BekmanTutorial Slides: mod_perl 2.0 By Example Slide 3
![Page 4: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/4.jpg)
Last modified Fri Jul 22 14:05:25 2005 GMT
Stas BekmanTutorial Slides: mod_perl 2.0 By Example Slide 4
![Page 5: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/5.jpg)
Stas BekmanGetting Your Feet Wet With mod_perl 2.0 Slide 5
![Page 6: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/6.jpg)
1�� Getting Your Feet WetWith mod_perl 2.0
Stas BekmanGetting Your Feet Wet With mod_perl 2.0 Slide 6
![Page 7: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/7.jpg)
1.1��AboutPrerequisites
Installation
Configuration
Server Launch and Shutdown
Registry Scripts
Handler Modules
Stas BekmanGetting Your Feet Wet With mod_perl 2.0 Slide 7
![Page 8: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/8.jpg)
1.2��PrerequisitesApache 2.0 is required.
mod_perl DSO: 2.0.47
static mod_perl: 2.0.51
Perl, depending on MPM:
prefork: 5.6.1 (no ithreads required)
threaded: 5.8.0 w/ithreads
The installation details are in the handouts
Stas BekmanGetting Your Feet Wet With mod_perl 2.0 Slide 8
![Page 9: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/9.jpg)
Static prefork build
5.6.1 or higher w/ ithreads
5.8.2 or higher w/o ithreads
Static threaded build
5.8.0 or higher w/ ithreads
threads.pm
Perl 5.8.1 or higher w/ithreads enabled
Stas BekmanGetting Your Feet Wet With mod_perl 2.0 Slide 9
![Page 10: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/10.jpg)
1.3��mod_perl Installation % lwp-download \ http://perl.apache.org/dist/mod_perl-2.0.01.tar.gz % tar -xvzf mod_perl-2.x.xx.tar.gz % cd modperl-2.0 % perl Makefile.PL MP_APXS=$HOME/httpd/bin/apxs % make && make test && make install
MP_APXS is a full path to the apxs executable
Stas BekmanGetting Your Feet Wet With mod_perl 2.0 Slide 10
![Page 11: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/11.jpg)
1.4��ConfigurationEnable DSO:
LoadModule perl_module modules/mod_perl.so
Enable the 1.0 compatibility layer
PerlModule Apache2::compat
Stas BekmanGetting Your Feet Wet With mod_perl 2.0 Slide 11
![Page 12: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/12.jpg)
1.5��Server Launch and Shutdown
Start:
% $HOME/httpd/prefork/bin/apachectl start
% tail -f $HOME/httpd/prefork/logs/error_log
[Fri Jul 22 09:39:55 2005] [notice] Apache/2.0.55-dev (Unix) mod_ssl/2.0.55-dev OpenSSL/0.9.7e DAV/2 mod_perl/2.0.2-dev Perl/v5.8.7 configured -- resuming normal operations
Stop:
Stas BekmanGetting Your Feet Wet With mod_perl 2.0 Slide 12
![Page 13: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/13.jpg)
% $HOME/httpd/prefork/bin/apachectl stop
Stas BekmanGetting Your Feet Wet With mod_perl 2.0 Slide 13
![Page 14: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/14.jpg)
1.6��Registry ScriptsConfiguration
Alias /perl/ /home/httpd/httpd-2.0/perl/ <Location /perl/> SetHandler perl-script PerlResponseHandler ModPerl::Registry PerlOptions +ParseHeaders Options +ExecCGI </Location>
Restart the server
Stas BekmanGetting Your Feet Wet With mod_perl 2.0 Slide 14
![Page 15: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/15.jpg)
A simple script:
#!/usr/bin/perl print "Content-type: text/plain\n\n"; print "mod_perl 2.0 rocks!\n";
Make it executable and readable:
% chmod a+rx /home/httpd/httpd-2.0/perl/rock.pl
Request:
% lwp-request http://localhost/perl/rock.pl mod_perl 2.0 rocks!
Stas BekmanGetting Your Feet Wet With mod_perl 2.0 Slide 15
![Page 16: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/16.jpg)
1.7��Handler Modules # /home/httpd/httpd-2.0/perl/MyApache2/Rocks.pm # package MyApache2::Rocks; use strict; use warnings; use Apache2::RequestRec (); use Apache2::RequestIO (); use Apache2::Const -compile => qw(OK); sub handler { my $r = shift; $r->content_type(’text/plain’); print "mod_perl 2.0 rocks!\n"; return Apache2::Const::OK; } 1;
Stas BekmanGetting Your Feet Wet With mod_perl 2.0 Slide 16
![Page 17: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/17.jpg)
Adjust @INC via a startup file
use lib qw(/home/httpd/httpd-2.0/perl);
loaded from httpd.conf:
PerlRequire /home/httpd/httpd-2.0/perl/startup.pl
Configure:
<Location /rocks> SetHandler perl-script PerlResponseHandler MyApache2::Rocks </Location>
Restart server
Stas BekmanGetting Your Feet Wet With mod_perl 2.0 Slide 17
![Page 18: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/18.jpg)
Issue request:
% lwp-request http://localhost/rocks mod_perl 2.0 rocks!
Stas BekmanGetting Your Feet Wet With mod_perl 2.0 Slide 18
![Page 19: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/19.jpg)
Stas BekmanNew Concepts Slide 19
![Page 20: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/20.jpg)
2�� New Concepts
Stas BekmanNew Concepts Slide 20
![Page 21: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/21.jpg)
2.1��AboutExceptions
Bucket Brigades
Stas BekmanNew Concepts Slide 21
![Page 22: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/22.jpg)
2.2��ExceptionsApache and APR API return a status code for almost all methods
In C you must check return value of each call
It makes it really hard/slow to prototype things
It makes the code hard to read
It’s easy to forget to check the return values -- causingproblems later
It complicates the API, when you may want to return other values
Stas BekmanNew Concepts Slide 22
![Page 23: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/23.jpg)
APR::Error handles APR/Apache/mod_perl exceptions foryou, while leaving you in control.
Instead of returning status codes, we throw exceptions
Stas BekmanNew Concepts Slide 23
![Page 24: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/24.jpg)
If you don’t catch those exceptions, everything works transparently
my $rlen = $sock->recv(my $buff, 1024);
Perl will intercept the exception object and die() with aproper error message.
[Wed Jun 09 07:25:25 2004] [error] [client 127.0.0.1] APR::Socket::recv: (11) Resource temporarily unavailable at .../TestError/runtime.pm line 124
Stas BekmanNew Concepts Slide 24
![Page 25: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/25.jpg)
If you want to catch an exception -- you can.
use APR::Status (); # # .... my $tries = 0; RETRY: my $rlen = eval { $sock->recv(my $buffer, SIZE) }; if ($@) { die $@ unless ref $@ && APR::Status::is_EAGAIN($@); if ($tries++ < 3) { # sleep 250msec select undef, undef, undef, 0.25; goto RETRY; } else { # do something else } } warn "read $rlen bytes\n"
Stas BekmanNew Concepts Slide 25
![Page 26: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/26.jpg)
APR::Status::is_FOO($@) is for complicated cases
most of the time it’ll be a simple compare:
use APR::Const -compile => qw(TIMEUP); # some code throwing an exception if ($@ && ref $@ && $@ == APR::Const::TIMEUP) { # do something }
Stas BekmanNew Concepts Slide 26
![Page 27: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/27.jpg)
APR::Error uses Perl operator overloading:
in boolean and numerical contexts -- gives the status code
in the string context -- the full error message
it is called APR::Error as it is used by
mod_perl
APR apps written in Perl
Stas BekmanNew Concepts Slide 27
![Page 28: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/28.jpg)
2.3��Bucket Brigades
Stas BekmanNew Concepts Slide 28
![Page 29: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/29.jpg)
Apache 2.0 implements request and response data flow filtering
Modules can filter each other’s output
No need to modify Apache to accomodate SSL,compressions, transformation filters.
The Bucket Brigades technology was introduced to make IOfiltering efficient and avoid unnecessary copying.
Stas BekmanNew Concepts Slide 29
![Page 30: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/30.jpg)
Buckets:
A bucket represents a chunk of data.
Buckets linked together comprise a brigade.
Each bucket in a brigade can be modified, removed andreplaced with another bucket.
Bucket types: files, data blocks, flush and end of streamindicators, pools, etc.
To manipulate a bucket one doesn’t need to know its internal representation.
Stas BekmanNew Concepts Slide 30
![Page 31: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/31.jpg)
Bucket Brigades:
A stream of data is represented by bucket brigades.
Filters manipulate brigades one by one(adding/modifying/removing buckets)
... and pass the brigade to the next filter on the stack
Stas BekmanNew Concepts Slide 31
![Page 32: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/32.jpg)
Here’s an imaginary bucket brigade after it has passedthrough several filters.
Stas BekmanNew Concepts Slide 32
![Page 33: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/33.jpg)
More about BBs when we talk about protocols and filters
Stas BekmanNew Concepts Slide 33
![Page 34: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/34.jpg)
Stas BekmanIntroducing mod_perl Handlers Slide 34
![Page 35: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/35.jpg)
3�� Introducing mod_perlHandlers
Stas BekmanIntroducing mod_perl Handlers Slide 35
![Page 36: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/36.jpg)
3.1��AboutHandler Anatomy
mod_perl Handlers Categories
Single Phase’s Multiple Handlers Behavior
Stas BekmanIntroducing mod_perl Handlers Slide 36
![Page 37: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/37.jpg)
3.2��Handler AnatomyApache distinguishes between numerous phases
Each phase provides a hook: ap_hook_<phase_name>
These hooks are used by modules to alter the default Apache behavior
Hooks are usually referred to as handlers or callbacks
Naming convention: PerlFooHandler
e.g. PerlResponseHandler configures the response callback.
Stas BekmanIntroducing mod_perl Handlers Slide 37
![Page 38: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/38.jpg)
package MyApache2::CurrentTime; use strict; use warnings; use Apache2::RequestRec (); use Apache2::RequestIO (); use Apache2::Const -compile => qw(OK); sub handler { my $r = shift; $r->content_type(’text/plain’); $r->print("The time is: " . scalar(localtime) . "\n"); return Apache2::Const::OK; } 1;
Stas BekmanIntroducing mod_perl Handlers Slide 38
![Page 39: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/39.jpg)
Configuring the response handler:
PerlModule MyApache2::CurrentTime <Location /time> SetHandler modperl PerlResponseHandler MyApache2::CurrentTime </Location>
A request to http://localhost/time returns the curent time
Stas BekmanIntroducing mod_perl Handlers Slide 39
![Page 40: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/40.jpg)
3.3��mod_perl Handler CategoriesThe mod_perl handlers can be divided by their application scopein several categories:
Server life cycle PerlOpenLogsHandler PerlPostConfigHandler PerlChildInitHandler PerlChildExitHandler
Protocols PerlPreConnectionHandler PerlProcessConnectionHandler
Stas BekmanIntroducing mod_perl Handlers Slide 40
![Page 41: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/41.jpg)
Filters PerlInputFilterHandler PerlOutputFilterHandler
HTTP Protocol PerlPostReadRequestHandler PerlTransHandler PerlMapToStorageHandler PerlInitHandler PerlHeaderParserHandler PerlAccessHandler PerlAuthenHandler PerlAuthzHandler PerlTypeHandler PerlFixupHandler PerlResponseHandler PerlLogHandler PerlCleanupHandler
Stas BekmanIntroducing mod_perl Handlers Slide 41
![Page 42: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/42.jpg)
3.4��Stacked HandlersPhases’ behavior varies when there is more then one handlerregistered to run for the same phase.
The following table specifies each handler’s behavior in this situation:
Stas BekmanIntroducing mod_perl Handlers Slide 42
![Page 43: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/43.jpg)
Directive Type # -------------------------------------- PerlOpenLogsHandler RUN_ALL PerlPostConfigHandler RUN_ALL PerlChildInitHandler VOID PerlChildExitHandler VOID PerlPreConnectionHandler RUN_ALL PerlProcessConnectionHandler RUN_FIRST PerlPostReadRequestHandler RUN_ALL PerlTransHandler RUN_FIRST PerlMapToStorageHandler RUN_FIRST PerlInitHandler RUN_ALL PerlHeaderParserHandler RUN_ALL PerlAccessHandler RUN_ALL PerlAuthenHandler RUN_FIRST PerlAuthzHandler RUN_FIRST PerlTypeHandler RUN_FIRST PerlFixupHandler RUN_ALL PerlResponseHandler RUN_FIRST PerlLogHandler RUN_ALL PerlCleanupHandler RUN_ALL PerlInputFilterHandler VOID PerlOutputFilterHandler VOID
Stas BekmanIntroducing mod_perl Handlers Slide 43
![Page 44: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/44.jpg)
The types:
VOID
Executed in the order they have been registereddisregarding their return values.
Though in mod_perl they are expected to return Apache2::Const::OK.
RUN_ALL
Executed in the order they have been registered until thefirst handler that returns something other than Apache2::Const::OK or Apache2::Const::DECLINED.
Stas BekmanIntroducing mod_perl Handlers Slide 44
![Page 45: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/45.jpg)
RUN_FIRST
Executed in the order they have been registered until thefirst handler that returns something other than Apache2::Const::DECLINED.
If the return value is Apache2::Const::DECLINED, thenext handler in the chain will be run.
If the return value is Apache2::Const::OK the nextphase will start.
In all other cases the execution will be aborted.
Stas BekmanIntroducing mod_perl Handlers Slide 45
![Page 46: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/46.jpg)
Stas BekmanServer Life Cycle Handlers Slide 46
![Page 47: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/47.jpg)
4�� Server Life CycleHandlers
Stas BekmanServer Life Cycle Handlers Slide 47
![Page 48: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/48.jpg)
4.1��AboutServer Life Cycle
Startup Phases Demonstration Module
PerlOpenLogsHandler
PerlPostConfigHandler
PerlChildInitHandler
PerlChildExitHandler
Stas BekmanServer Life Cycle Handlers Slide 48
![Page 49: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/49.jpg)
4.2��Apache 2.0 Server Life Cycle
Stas BekmanServer Life Cycle Handlers Slide 49
![Page 50: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/50.jpg)
Stas BekmanServer Life Cycle Handlers Slide 50
![Page 51: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/51.jpg)
1. Parse the configuration file, open_logs, post_config
2. Restart to test graceful restarts
3. Parse the configuration file, open_logs, post_config
4. Spawn workers: procs, threads, mix
Run child_init for each spawned process
5. Process requests over connections
6. Shutdown: child_exit
Stas BekmanServer Life Cycle Handlers Slide 51
![Page 52: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/52.jpg)
4.2.1��Startup PhasesDemonstration Module package MyApache2::StartupLog; # use strict; use warnings; use Apache2::Log (); use Apache2::ServerUtil (); use Fcntl qw(:flock); use File::Spec::Functions; use Apache2::Const -compile => ’OK’; my $log_path = catfile Apache2::ServerUtil::server_root, "logs", "startup_log"; my $log_fh;
Stas BekmanServer Life Cycle Handlers Slide 52
![Page 53: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/53.jpg)
sub open_logs { my($conf_pool, $log_pool, $temp_pool, $s) = @_; $s->warn("opening the log file: $log_path"); open $log_fh, ">>$log_path" or die "can’t open $log_path: $!"; my $oldfh = select($log_fh); $| = 1; select($oldfh); say("process $$ is born to reproduce"); return Apache2::Const::OK; } sub post_config { my($conf_pool, $log_pool, $temp_pool, $s) = @_; say("configuration is completed"); return Apache2::Const::OK; } sub child_init { # my($child_pool, $s) = @_; say("process $$ is born to serve"); return Apache2::Const::OK; }
Stas BekmanServer Life Cycle Handlers Slide 53
![Page 54: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/54.jpg)
sub child_exit { # my($child_pool, $s) = @_; say("process $$ now exits"); return Apache2::Const::OK; } sub say { my($caller) = (caller(1))[3] =~ /([^:]+)$/; if (defined $log_fh) { flock $log_fh, LOCK_EX; printf $log_fh "[%s] - %-11s: %s\n", scalar(localtime), $caller, $_[0]; flock $log_fh, LOCK_UN; } else { # when the log file is not open warn __PACKAGE__ . " says: $_[0]\n"; } }
Stas BekmanServer Life Cycle Handlers Slide 54
![Page 55: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/55.jpg)
my $parent_pid = $$; # END { my $msg = "process $$ is shutdown"; $msg .= "\n". "-" x 20 if $$ == $parent_pid; say($msg); } 1;
Stas BekmanServer Life Cycle Handlers Slide 55
![Page 56: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/56.jpg)
And the httpd.conf configuration section:
PerlModule MyApache2::StartupLog PerlOpenLogsHandler MyApache2::StartupLog::open_logs PerlPostConfigHandler MyApache2::StartupLog::post_config PerlChildInitHandler MyApache2::StartupLog::child_init PerlChildExitHandler MyApache2::StartupLog::child_exit
Stas BekmanServer Life Cycle Handlers Slide 56
![Page 57: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/57.jpg)
% bin/apachectl start
# logs/startup_log>: [Sun Jun 6 01:50:06 2004] - open_logs : process 24189 is born to reproduce [Sun Jun 6 01:50:06 2004] - post_config: configuration is completed [Sun Jun 6 01:50:07 2004] - END : process 24189 is shutdown -------------------- [Sun Jun 6 01:50:08 2004] - open_logs : process 24190 is born to reproduce [Sun Jun 6 01:50:08 2004] - post_config: configuration is completed [Sun Jun 6 01:50:09 2004] - child_init : process 24192 is born to serve [Sun Jun 6 01:50:09 2004] - child_init : process 24193 is born to serve [Sun Jun 6 01:50:09 2004] - child_init : process 24194 is born to serve [Sun Jun 6 01:50:09 2004] - child_init : process 24195 is born to serve
Apache restarts itself
Stas BekmanServer Life Cycle Handlers Slide 57
![Page 58: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/58.jpg)
% bin/apachectl stop
[Sun Jun 6 01:50:10 2004] - child_exit : process 24193 now exits [Sun Jun 6 01:50:10 2004] - END : process 24193 is shutdown [Sun Jun 6 01:50:10 2004] - child_exit : process 24194 now exits [Sun Jun 6 01:50:10 2004] - END : process 24194 is shutdown [Sun Jun 6 01:50:10 2004] - child_exit : process 24195 now exits [Sun Jun 6 01:50:10 2004] - child_exit : process 24192 now exits [Sun Jun 6 01:50:10 2004] - END : process 24192 is shutdown [Sun Jun 6 01:50:10 2004] - END : process 24195 is shutdown [Sun Jun 6 01:50:10 2004] - END : process 24190 is shutdown --------------------
All processes run the END block on shutdown
Stas BekmanServer Life Cycle Handlers Slide 58
![Page 59: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/59.jpg)
The presented behavior varies from MPM to MPM.
I used prefork MPM for this demo
MPMs, like winnt, may run open_logs and post_config morethan once
the END blocks may be run more times, when threads are involved.
The only sure thing -- each of these phases runs at least once
Stas BekmanServer Life Cycle Handlers Slide 59
![Page 60: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/60.jpg)
Stas BekmanProtocol Handlers Slide 60
![Page 61: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/61.jpg)
5�� Protocol Handlers
Stas BekmanProtocol Handlers Slide 61
![Page 62: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/62.jpg)
5.1��AboutConnection Cycle Phases
PerlPreConnectionHandler
PerlProcessConnectionHandler
Socket-based Protocol Module
Bucket Brigades-based Protocol Module
Stas BekmanProtocol Handlers Slide 62
![Page 63: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/63.jpg)
5.2��Connection Cycle PhasesEach child server is engaged in processing connections.
Each connection may be served by different connection protocols,
e.g., HTTP, POP3, SMTP, etc.
Each connection may include more than one request,
e.g., several HTTP requests can be served over a singleconnection, when a response includes several images.
Stas BekmanProtocol Handlers Slide 63
![Page 64: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/64.jpg)
Connection Life Cycle diagram:
Stas BekmanProtocol Handlers Slide 64
![Page 65: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/65.jpg)
Stas BekmanProtocol Handlers Slide 65
![Page 66: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/66.jpg)
5.2.1��PerlPreConnectionHandler
The pre_connection phase happens just after the serveraccepts the connection, but before it is handed off to aprotocol module to be served.
Stas BekmanProtocol Handlers Slide 66
![Page 67: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/67.jpg)
It gives modules an opportunity to modify the connection assoon as possible and insert filters if needed.
The core server uses this phase to setup the connectionrecord based on the type of connection that is being used.
mod_perl itself uses this phase to register the connectioninput and output filters.
Stas BekmanProtocol Handlers Slide 67
![Page 68: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/68.jpg)
Apache2::Reload:
In mod_perl 1.0 Apache::Reload was used to automaticallyreload modified since the last request Perl modules.
It was invoked during post_read_request, the first HTTPrequest’s phase.
In mod_perl 2.0 pre_connection is the earliest general phase
So now we can invoke the Apache2::Reload handlerduring the pre_connection phase if the interpreter’s scope is:
PerlInterpScope connection
Stas BekmanProtocol Handlers Slide 68
![Page 69: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/69.jpg)
Though this is not good for a production server,
where there are several requests coming on the same connection
and only one handled by mod_perl
and the others by the default images handler
the Perl interpreter won’t be available to other threads whilethe images are being served.
Stas BekmanProtocol Handlers Slide 69
![Page 70: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/70.jpg)
Skeleton:
sub handler { my $c = shift; # ... return Apache2::Const::OK; }
A pre_connection handler accepts one argument:
connection record
Stas BekmanProtocol Handlers Slide 70
![Page 71: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/71.jpg)
Block by IP example:
package MyApache2::BlockIP2; # use Apache2::Connection (); use Apache2::Const -compile => qw(FORBIDDEN OK); my %bad_ips = map {$_ => 1} qw(127.0.0.1 10.0.0.4); sub handler { my $c = shift; my $ip = $c->remote_ip; if (exists $bad_ips{$ip}) { warn "IP $ip is blocked\n"; return Apache2::Const::FORBIDDEN; } return Apache2::Const::OK; } 1;
Stas BekmanProtocol Handlers Slide 71
![Page 72: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/72.jpg)
Configuration
PerlPreConnectionHandler MyApache2::BlockIP2
Apache simply drops the connection if the IP is blacklisted
Almost no resources are wasted
Stas BekmanProtocol Handlers Slide 72
![Page 73: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/73.jpg)
5.2.2��PerlProcessConnectionHandler
The process_connection phase is used to process incoming connections.
Stas BekmanProtocol Handlers Slide 73
![Page 74: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/74.jpg)
Only protocol modules should assign handlers for this phase,as it gives them an opportunity to replace the standard HTTPprocessing with processing for some other protocols (e.g., POP3,FTP, etc.).
The only way to run protocol servers different than the coreHTTP is inside dedicated virtual hosts.
Stas BekmanProtocol Handlers Slide 74
![Page 75: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/75.jpg)
process_connection skeleton:
sub handler { my ($c) = @_; my $sock = $c->client_socket; $sock->opt_set(APR::Const::SO_NONBLOCK, 0); # ... return Apache2::Const::OK; }
arg1: a connection record object
a socket object: retrieved from $c
must set the socket to blocking IO mode
Stas BekmanProtocol Handlers Slide 75
![Page 76: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/76.jpg)
Let’s look at the following two examples of connection handlers:
1. Using the connection socket to read and write the data.
2. Using bucket brigades to accomplish the same and allowfor connection filters to do their work.
Stas BekmanProtocol Handlers Slide 76
![Page 77: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/77.jpg)
5.2.2.1��Socket-based Protocol Module
The MyApache2::EchoSocket module simply echoes thedata read back to the client.
This module’s implementation works directly with theconnection socket and therefore bypasses connection filters if any.
Stas BekmanProtocol Handlers Slide 77
![Page 78: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/78.jpg)
Configuration:
Listen 8010 <VirtualHost _default_:8010> PerlModule MyApache2::EchoSocket PerlProcessConnectionHandler MyApache2::EchoSocket </VirtualHost>
use the Listen and <VirtualHost> directives to bind tothe non-standard port 8010:
Stas BekmanProtocol Handlers Slide 78
![Page 79: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/79.jpg)
Demo:
panic% httpd panic% telnet localhost 8010 Trying 127.0.0.1... Connected to localhost (127.0.0.1). Escape character is ’^]’. Hello Hello fOo BaR fOo BaR
Connection closed by foreign host.
Stas BekmanProtocol Handlers Slide 79
![Page 80: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/80.jpg)
The code:
package MyApache2::EchoSocket; # use strict; use warnings FATAL => ’all’; use Apache2::Connection (); use APR::Socket (); use Apache2::Const -compile => ’OK’; use APR::Const -compile => ’SO_NONBLOCK’; use constant BUFF_LEN => 1024;
Stas BekmanProtocol Handlers Slide 80
![Page 81: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/81.jpg)
sub handler { # my $c = shift; my $sock = $c->client_socket; $sock->opt_set(APR::Const::SO_NONBLOCK => 0); while ($sock->recv(my $buff, BUFF_LEN)) { last if $buff =~ /^[\r\n]+$/; $sock->send($buff); } Apache2::Const::OK; } 1;
Stas BekmanProtocol Handlers Slide 81
![Page 82: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/82.jpg)
5.2.2.2��Bucket Brigades-based Protocol Module
The same module, but this time implemented by manipulatingbucket brigades,
and which runs its output through a connection output filterthat turns all uppercase characters into their lowercase equivalents.
Stas BekmanProtocol Handlers Slide 82
![Page 83: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/83.jpg)
Configuration:
Listen 8011 <VirtualHost _default_:8011> PerlModule MyApache2::EchoBB PerlProcessConnectionHandler MyApache2::EchoBB PerlOutputFilterHandler MyApache2::EchoBB::lowercase_filter </VirtualHost>
Stas BekmanProtocol Handlers Slide 83
![Page 84: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/84.jpg)
Demo:
panic% httpd panic% telnet localhost 8011 Trying 127.0.0.1... Connected to localhost (127.0.0.1). Escape character is ’^]’. Hello hello fOo BaR foo bar
As you can see the response now was all in lower case,because of the output filter.
Stas BekmanProtocol Handlers Slide 84
![Page 85: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/85.jpg)
The code:
package MyApache2::EchoBB; # use strict; use warnings FATAL => ’all’; use Apache2::Connection (); use APR::Socket (); use APR::Bucket (); use APR::Brigade (); use APR::Error (); use APR::Status (); use APR::Const -compile => qw(SUCCESS SO_NONBLOCK); use Apache2::Const -compile => qw(OK MODE_GETLINE);
Stas BekmanProtocol Handlers Slide 85
![Page 86: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/86.jpg)
sub handler { # my $c = shift; $c->client_socket->opt_set(APR::Const::SO_NONBLOCK => 0); my $bb_in = APR::Brigade->new($c->pool, $c->bucket_alloc); my $bb_out = APR::Brigade->new($c->pool, $c->bucket_alloc); my $last = 0; while (1) { my $rc = $c->input_filters->get_brigade($bb_in, Apache2::Const::MODE_GETLINE); last if APR::Status::is_EOF($rc); die APR::Error::strerror($rc) unless $rc == APR::Const::SUCCESS;
Stas BekmanProtocol Handlers Slide 86
![Page 87: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/87.jpg)
while (!$bb_in->empty) { # my $b = $bb_in->first; $b->remove; if ($b->is_eos) { $bb_out->insert_tail($b); last; } if ($b->read(my $data)) { $last++ if $data =~ /^[\r\n]+$/; # could do some transformation on data here $b = APR::Bucket->new($bb_out->bucket_alloc, $data); } $bb_out->insert_tail($b); }
Stas BekmanProtocol Handlers Slide 87
![Page 88: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/88.jpg)
my $fb = APR::Bucket::flush_create($c->bucket_alloc); # $bb_out->insert_tail($fb); $c->output_filters->pass_brigade($bb_out); last if $last; } $bb_in->destroy; $bb_out->destroy; Apache2::Const::OK; }
Stas BekmanProtocol Handlers Slide 88
![Page 89: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/89.jpg)
use base qw(Apache2::Filter); # use constant BUFF_LEN => 1024; sub lowercase_filter : FilterConnectionHandler { my $filter = shift; while ($filter->read(my $buffer, BUFF_LEN)) { $filter->print(lc $buffer); } return Apache2::Const::OK; } 1;
Stas BekmanProtocol Handlers Slide 89
![Page 90: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/90.jpg)
A simplified pseudo-code handler:
while ($bb_in = get_brigade()) { while ($b_in = $bb_in->get_bucket()) { # $b_in->read(my $data); # do something with $data $b_out = new_bucket($data); $bb_out->insert_tail($b_out); } $bb_out->insert_tail($flush_bucket); pass_brigade($bb_out); }
Stas BekmanProtocol Handlers Slide 90
![Page 91: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/91.jpg)
Use fflush -- replace:
my $fb = APR::Bucket::flush_create($c->bucket_alloc); # $bb_out->insert_tail($fb); $c->output_filters->pass_brigade($bb_out);
with just one line:
$c->output_filters->fflush($bb_out); #
Stas BekmanProtocol Handlers Slide 91
![Page 92: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/92.jpg)
The same handler using a single bucket brigade
sub handler { my $c = shift; $c->client_socket->opt_set(APR::Const::SO_NONBLOCK, 0); my $bb = APR::Brigade->new($c->pool, $c->bucket_alloc); while (1) { my $rc = $c->input_filters->get_brigade($bb, Apache2::Const::MODE_GETLINE); last if APR::Status::is_EOF($rc); die APR::Error::strerror($rc) unless $rc == APR::Const::SUCCESS; for (my $b = $bb->first; $b; $b = $bb->next($b)) { last if $b->is_eos; if ($b->read(my $data)) { last if $data =~ /^[\r\n]+$/; my $nb = APR::Bucket->new($bb->bucket_alloc, $data); # head->...->$nb->$b ->...->tail $b->insert_before($nb); $b->remove; } } $c->output_filters->fflush($bb); }
Stas BekmanProtocol Handlers Slide 92
![Page 93: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/93.jpg)
$bb->destroy; Apache2::Const::OK; }
Stas BekmanProtocol Handlers Slide 93
![Page 94: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/94.jpg)
This handler could be much simpler, since we don’t modifythe data.
$c->client_socket->opt_set(APR::Const::SO_NONBLOCK => 0); my $bb = APR::Brigade->new($c->pool, $c->bucket_alloc); while (1) { my $rc = $c->input_filters->get_brigade($bb, Apache2::Const::MODE_GETLINE); last if APR::Status::is_EOF($rc); die APR::Error::strerror($rc) unless $rc == APR::Const::SUCCESS; $c->output_filters->fflush($bb); } $bb->destroy;
but it won’t work in the telnet mode, since /[\r\n]/ that wetype to end the line will keep this loop running forever
Stas BekmanProtocol Handlers Slide 94
![Page 95: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/95.jpg)
And here is another version which slurps all the data andworks with telnet
my $bb = APR::Brigade->new($c->pool, $c->bucket_alloc); while (1) { my $rc = $c->input_filters->get_brigade($bb, Apache2::Const::MODE_GETLINE); last if APR::Status::is_EOF($rc); die APR::Error::strerror($rc) unless $rc == APR::Const::SUCCESS; next unless $bb->flatten(my $data); $bb->cleanup; last if $data =~ /^[\r\n]+$/; my $b = APR::Bucket->new($bb->bucket_alloc, $data); $bb->insert_tail($b); $c->output_filters->fflush($bb); } $bb->destroy;
Stas BekmanProtocol Handlers Slide 95
![Page 96: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/96.jpg)
We will discuss the filters next
Stas BekmanProtocol Handlers Slide 96
![Page 97: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/97.jpg)
Stas BekmanInput and Output Filters Slide 97
![Page 98: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/98.jpg)
6�� Input and Output Filters
Stas BekmanInput and Output Filters Slide 98
![Page 99: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/99.jpg)
6.1��AboutYour First Filter
I/O Filtering Concepts
Two Methods for Manipulating Data
HTTP Request Versus Connection Filters
Multiple Invocations of Filter Handlers
Blocking Calls
Stas BekmanInput and Output Filters Slide 99
![Page 100: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/100.jpg)
mod_perl Filters Declaration and Configuration
Filter Priority Types
PerlInputFilterHandler
PerlOutputFilterHandler
PerlSetInputFilter
PerlSetOutputFilter
HTTP Request vs. Connection Filters
Filter Initialization Phase
Stas BekmanInput and Output Filters Slide 100
![Page 101: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/101.jpg)
All-in-One Filter
Input Filters Examples
Output Filters Examples
Stas BekmanInput and Output Filters Slide 101
![Page 102: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/102.jpg)
6.2��Your First FilterYou certainly already know how filters work.
That’s because you encounter filters so often in real life.
Stas BekmanInput and Output Filters Slide 102
![Page 103: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/103.jpg)
Stas BekmanInput and Output Filters Slide 103
![Page 104: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/104.jpg)
Stas BekmanInput and Output Filters Slide 104
![Page 105: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/105.jpg)
Stas BekmanInput and Output Filters Slide 105
![Page 106: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/106.jpg)
Stas BekmanInput and Output Filters Slide 106
![Page 107: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/107.jpg)
Stas BekmanInput and Output Filters Slide 107
![Page 108: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/108.jpg)
Stas BekmanInput and Output Filters Slide 108
![Page 109: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/109.jpg)
Stas BekmanInput and Output Filters Slide 109
![Page 110: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/110.jpg)
Why using I/O filters?
Instead of making the response handler code complex
adjust its output with filters:
each doing a simple transformation
and can be:
stacked
repeated
added/removed dynamically at run-time
Stas BekmanInput and Output Filters Slide 110
![Page 111: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/111.jpg)
6.3��A Few Quick ExamplesA typical Configuration
<Location ...> PerlOutputFilterHandler Modulename::handlername </Location>
Stas BekmanInput and Output Filters Slide 111
![Page 112: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/112.jpg)
The simplest pass through filter
package MyApache2::FilterTryPassThrough; # use strict; use warnings FATAL => ’all’; use Apache2::Const -compile => qw(DECLINED); sub filter { #warn __PACKAGE__ . ": filter called\n"; return Apache2::Const::DECLINED; } 1;
Stas BekmanInput and Output Filters Slide 112
![Page 113: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/113.jpg)
Another pass through filter
package MyApache2::FilterTryPassThrough2; # use strict; use warnings FATAL => ’all’; use Apache2::Filter (); use Apache2::Const -compile => qw(OK); sub filter { my $f = shift; while ($f->read(my $buffer, 1024)){ $f->print($buffer); } return Apache2::Const::OK; } 1;
Stas BekmanInput and Output Filters Slide 113
![Page 114: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/114.jpg)
A lowercase filter
convert:
<HTML><body></body></HTML>
to:
<html><body></body></html>
Stas BekmanInput and Output Filters Slide 114
![Page 115: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/115.jpg)
package MyApache2::FilterTryLC; # use strict; use warnings FATAL => ’all’; use Apache2::Filter (); use Apache2::Const -compile => qw(OK); sub filter { my $f = shift; while ($f->read(my $buffer, 1024)){ $f->print(lc $buffer); } return Apache2::Const::OK; } 1;
Stas BekmanInput and Output Filters Slide 115
![Page 116: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/116.jpg)
A simple web ad blocker filter
turn:
<html> <body> <img src="ad.png"> </body> </html>
into:
<html> <body> </body> </html>
Stas BekmanInput and Output Filters Slide 116
![Page 117: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/117.jpg)
package MyApache2::FilterTryAdBlock; # use strict; use warnings FATAL => ’all’; use Apache2::Filter (); use Apache2::RequestRec (); use APR::Table (); use Apache2::Const -compile => qw(OK);
Stas BekmanInput and Output Filters Slide 117
![Page 118: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/118.jpg)
sub filter { # my $f = shift; unless ($f->ctx) { $f->r->headers_out->unset(’Content-Length’); $f->ctx(1); } while ($f->read(my $buffer, 1024)) { $buffer =~ s|<img[^>]+>||ig; $f->print($buffer); } return Apache2::Const::OK; } 1;
Stas BekmanInput and Output Filters Slide 118
![Page 119: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/119.jpg)
A more robust simple web ad blocker filter
deal with "sliced" input
<html> <body> <img
followed by:
src="ad.png"> </body> </html>
Stas BekmanInput and Output Filters Slide 119
![Page 120: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/120.jpg)
package MyApache2::FilterTryAdBlockAdv; # use strict; use warnings FATAL => ’all’; use Apache2::Filter (); use Apache2::RequestRec (); use APR::Table (); use Apache2::Const -compile => qw(OK);
Stas BekmanInput and Output Filters Slide 120
![Page 121: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/121.jpg)
sub filter { # my $f = shift; my $data = $f->ctx; $data = "" unless defined $data; while ($f->read(my $buffer, 1024)) { $data .= $buffer if defined $buffer; } if ($f->seen_eos) { $data =~ s|<img[^>]+>||ig; $f->r->headers_out->unset(’Content-Length’); $f->print($data) if defined $data; } else { $f->ctx($data) if defined $data; } return Apache2::Const::OK; } 1;
Stas BekmanInput and Output Filters Slide 121
![Page 122: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/122.jpg)
since we have buffered the data up, instead of deleting theC-L header, we can set it to the correct value:
if ($f->seen_eos) { $data =~ s|<img[^>]+>||ig; my $len = defined $data ? length $data : 0; $f->r->headers_out->set(’Content-Length’, $len); $f->print($data) if defined $data; } ...
Stas BekmanInput and Output Filters Slide 122
![Page 123: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/123.jpg)
The same filter using bucket brigades
package MyApache2::FilterTryAdBlockBB; # use strict; use warnings FATAL => ’all’; use Apache2::Filter (); use Apache2::RequestRec (); use APR::Brigade (); use APR::Bucket (); use APR::Table (); use Apache2::Const -compile => qw(OK);
Stas BekmanInput and Output Filters Slide 123
![Page 124: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/124.jpg)
sub bb_data_n_eos { # my $bb = shift; my $seen_eos = 0; my @data; for (my $b = $bb->first; $b; $b = $bb->next($b)) { $seen_eos++, last if $b->is_eos; $b->read(my $bdata); push @data, $bdata; } return (join(’’, @data), $seen_eos); }
Stas BekmanInput and Output Filters Slide 124
![Page 125: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/125.jpg)
sub filter { # my($f, $bb) = @_; my $data = $f->ctx; $data = "" unless defined $data; my($buffer, $seen_eos) = bb_data_n_eos($bb); $data .= $buffer if defined $buffer; if ($seen_eos) { $data =~ s|<img[^>]+>||ig; $f->r->headers_out->unset(’Content-Length’); $f->print($data) if defined $data; } else { $f->ctx($data) if defined $data; } return Apache2::Const::OK; } 1;
Stas BekmanInput and Output Filters Slide 125
![Page 126: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/126.jpg)
6.4��I/O Filtering ConceptsBefore getting to the real filter examples
a few concepts to help you wrap your head around ...
Stas BekmanInput and Output Filters Slide 126
![Page 127: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/127.jpg)
6.4.1��2 Ways to Manipulate DataApache 2.0 considers all incoming and outgoing data aschunks of information,
disregarding their kind and source or storage methods.
These data chunks are stored in buckets, which form bucket brigades.
Both input and output filters, filter the data in bucket brigades.
Stas BekmanInput and Output Filters Slide 127
![Page 128: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/128.jpg)
Stas BekmanInput and Output Filters Slide 128
![Page 129: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/129.jpg)
mod_perl 2.0 filters can:
directly manipulate the bucket brigades
use a simplified streaming interface
the filter object acts similar to a filehandle,
which can be read from and printed to.
Stas BekmanInput and Output Filters Slide 129
![Page 130: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/130.jpg)
6.4.2��HTTP Request vsConnection FiltersHTTP Request filters
are applied on:
HTTP requests body (POST) (if consumed by the content handler)
HTTP response body
HTTP headers are not passed through the HTTP Request filters.
Stas BekmanInput and Output Filters Slide 130
![Page 131: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/131.jpg)
Stas BekmanInput and Output Filters Slide 131
![Page 132: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/132.jpg)
Connections filters:
are applied at the connection level.
can modify all the incoming and outgoing data.
including HTTP headers if HTTP protocol is used
Stas BekmanInput and Output Filters Slide 132
![Page 133: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/133.jpg)
Stas BekmanInput and Output Filters Slide 133
![Page 134: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/134.jpg)
6.4.3��Multiple Invocations ofFilter Handlers
a filter gets invoked as many times as the number of bucketbrigades sent from an upstream filter or a content provider.
Response handler example, buffered STDOUT ($|==0):
$r->print("foo"); $r->rflush; $r->print("bar");
Apache generates 3 bucket brigades => 3 filter invocations
Stas BekmanInput and Output Filters Slide 134
![Page 135: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/135.jpg)
print and rflush => two buckets:
bucket type data ---------------------- 1st transient foo 2nd flush
print => one bucket:
bucket type data ---------------------- 1st transient bar
when the response handler returns => one bucket:
bucket type data ---------------------- 1st eos
Stas BekmanInput and Output Filters Slide 135
![Page 136: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/136.jpg)
EOS may come as a last bucket in bb with data
Stas BekmanInput and Output Filters Slide 136
![Page 137: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/137.jpg)
Three Filter Stages:
Stas BekmanInput and Output Filters Slide 137
![Page 138: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/138.jpg)
Filter skeleton demonstrating all 3 stages:
sub handler { my $f = shift; unless ($f->ctx) { # runs on the first invocation init($f); $f->ctx(1); } process($f); # runs on all invocations if ($f->seen_eos) { # runs on the last invocation finalize($f); } return Apache2::Const::OK; }
Stas BekmanInput and Output Filters Slide 138
![Page 139: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/139.jpg)
Init example:
response filters changing data length have to unset the C-Lheader (runs once)
unless ($f->ctx) { $f->r->headers_out->unset(’Content-Length’); $f->ctx(1); }
Stas BekmanInput and Output Filters Slide 139
![Page 140: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/140.jpg)
Processing example:
lower the data case (runs on all invocations)
while ($f->read(my $data, 1024)) { $f->print(lc $data); }
in complex cases may need to store data in context betweenfilter invocations
Stas BekmanInput and Output Filters Slide 140
![Page 141: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/141.jpg)
Finalization example:
After all data was sent out, print how many times the filter was invoked
my $ctx = $f->ctx; $ctx->{invoked}++; $f->ctx($ctx); # store while ($f->read(my $data, READ_SIZE)) { $f->print(lc $data); } if ($f->seen_eos) { $f->print("Filter invocated $ctx->{invoked} times"); }
Stas BekmanInput and Output Filters Slide 141
![Page 142: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/142.jpg)
6.4.4��Blocking CallsData propogates in stages through the filter chain (there is no pipeline)
The input filter’s get_brigade() call blocks
Stas BekmanInput and Output Filters Slide 142
![Page 143: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/143.jpg)
The output filter’s pass_brigade() call blocks
Stas BekmanInput and Output Filters Slide 143
![Page 144: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/144.jpg)
Transparent input filter:
sub in { my ($f, $bb, $mode, $block, $readbytes) = @_; my $rv = $f->next->get_brigade($bb, $mode, $block, $readbytes); return $rv unless $rv == APR::Const::SUCCESS; return Apache2::Const::OK; }
Transparent output filter:
sub out { my ($f, $bb) = @_; my $rv = $f->next->pass_brigade($bb); # return $rv unless $rv == APR::Const::SUCCESS; return Apache2::Const::OK; } 1;
Stas BekmanInput and Output Filters Slide 144
![Page 145: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/145.jpg)
6.5��mod_perl FiltersDeclaration and Configuration
Now let’s see how mod_perl filters are declared and configured.
Stas BekmanInput and Output Filters Slide 145
![Page 146: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/146.jpg)
6.5.1��Filter Priority TypesFilters are inserted into the filter chain based on their priority
mod_perl provides 2 filters types:
Handler Priority Value ------------------------------------------------- FilterRequestHandler AP_FTYPE_RESOURCE 10 FilterConnectionHandler AP_FTYPE_PROTOCOL 30
Apache provides others as well
Stas BekmanInput and Output Filters Slide 146
![Page 147: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/147.jpg)
6.5.2��PerlInputFilterHandlerThe PerlInputFilterHandler handler:
registers a filter for input filtering
and inserts it into the input filters chain.
automatically AutoLoaded:
PerlInputFilterHandler MyApache2::FilterTest PerlInputFilterHandler MyApache2::FilterTest::lc
avoid autoloading:
PerlInputFilterHandler -MyApache2::FilterTest::lc
Stas BekmanInput and Output Filters Slide 147
![Page 148: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/148.jpg)
6.5.3��PerlOutputFilterHandlerThe PerlOutputFilterHandler handler:
registers an output filter
and inserts it into the output filters chain.
automatically AutoLoaded like PerlInputFilterHandler
Stas BekmanInput and Output Filters Slide 148
![Page 149: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/149.jpg)
6.5.4��PerlSetInputFiltermod_perl equivalent for SetInputFilter
makes sure that mod_perl and non-mod_perl input filters ofthe same priority get inserted in the order they are configured
Stas BekmanInput and Output Filters Slide 149
![Page 150: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/150.jpg)
For example:
PerlSetInputFilter FILTER_FOO PerlInputFilterHandler MyApache2::FilterInputFoo
response handler /\ FILTER_FOO /\ MyApache2::FilterInputFoo /\ core input filters /\ network
Stas BekmanInput and Output Filters Slide 150
![Page 151: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/151.jpg)
6.5.5��PerlSetOutputFiltermod_perl equivalent for SetOutputFilter
makes sure that mod_perl and non-mod_perl output filters ofthe same priority get inserted in the order they are configured
Stas BekmanInput and Output Filters Slide 151
![Page 152: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/152.jpg)
For example:
PerlSetOutputFilter INCLUDES PerlOutputFilterHandler MyApache2::FilterOutputFoo
response handler \/ INCLUDES \/ MyApache2::FilterOutputFoo \/ core output filters \/ network
Stas BekmanInput and Output Filters Slide 152
![Page 153: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/153.jpg)
If filters have different priorities the insertion order might be different:
PerlSetOutputFilter DEFLATE PerlSetOutputFilter INCLUDES PerlOutputFilterHandler MyApache2::FilterOutputFoo
response handler \/ INCLUDES \/ MyApache2::FilterOutputFoo \/ DEFLATE \/ core output filters \/ network
Stas BekmanInput and Output Filters Slide 153
![Page 154: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/154.jpg)
6.5.6��Adding OutputFilters Dynamically
one can push filter callbacks at request time
e.g. add an output filter at fixup phase
<Files *\.html > PerlFixupHandler MyApache2::AddFilterDyn </Files>
package MyApache2::AddFilterDyn; use Apache2::Filter; use MyApache2::FilterObfuscate; use Apache2::Const -compile => qw(OK); sub handler {
Stas BekmanInput and Output Filters Slide 154
![Page 155: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/155.jpg)
my $r = shift; $r->add_output_filter(\&MyApache2::FilterObfuscate::handler); return Apache2::Const::OK; } 1;
Stas BekmanInput and Output Filters Slide 155
![Page 156: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/156.jpg)
6.5.7��HTTP Request vs.Connection Filters
method attributes set the filter type:
sub handler : FilterRequestHandler { ... } sub handler : FilterConnectionHandler { ... }
Stas BekmanInput and Output Filters Slide 156
![Page 157: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/157.jpg)
HTTP Request filter handlers are declared using the FilterRequestHandler attribute.
HTTP request input and output filters skeleton:
package MyApache2::FilterRequestFoo; use base qw(Apache2::Filter); sub input : FilterRequestHandler { my($f, $bb, $mode, $block, $readbytes) = @_; #... } sub output : FilterRequestHandler { my($f, $bb) = @_; #... } 1;
Stas BekmanInput and Output Filters Slide 157
![Page 158: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/158.jpg)
If the attribute is not specified, the default FilterRequestHandler attribute is assumed.
Filters specifying subroutine attributes must sub-class Apache2::Filter, others only need to:
use Apache2::Filter ();
Stas BekmanInput and Output Filters Slide 158
![Page 159: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/159.jpg)
Request filters are usually configured in the <Location> orequivalent sections:
PerlModule MyApache2::FilterRequestFoo PerlModule MyApache2::NiceResponse <Location /filter_foo> SetHandler modperl PerlResponseHandler MyApache2::NiceResponse PerlInputFilterHandler MyApache2::FilterRequestFoo::input PerlOutputFilterHandler MyApache2::FilterRequestFoo::output </Location>
Stas BekmanInput and Output Filters Slide 159
![Page 160: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/160.jpg)
Connection filter handlers are declared using the FilterConnectionHandler attribute.
Connection input and output filters skeleton:
package MyApache2::FilterConnectionBar; use base qw(Apache2::Filter); sub input : FilterConnectionHandler { my($f, $bb, $mode, $block, $readbytes) = @_; #... } sub output : FilterConnectionHandler { my($f, $bb) = @_; #... } 1;
Stas BekmanInput and Output Filters Slide 160
![Page 161: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/161.jpg)
This time the configuration must be done outside the <Location> or equivalent sections,
usually within the <VirtualHost> or the global server configuration:
Listen 8005 <VirtualHost _default_:8005> PerlModule MyApache2::FilterConnectionBar PerlModule MyApache2::NiceResponse PerlInputFilterHandler MyApache2::FilterConnectionBar::input PerlOutputFilterHandler MyApache2::FilterConnectionBar::output <Location /> SetHandler modperl PerlResponseHandler MyApache2::NiceResponse </Location> </VirtualHost>
Stas BekmanInput and Output Filters Slide 161
![Page 162: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/162.jpg)
For HTTP requests the only difference between connectionfilters and request filters is that the former see everything: theheaders and the body, whereas the latter see only the body.
mod_perl provides two interfaces to filtering:
a direct mapping to buckets and bucket brigades
and a simpler, stream-oriented interface
Following examples will explain the difference
Stas BekmanInput and Output Filters Slide 162
![Page 163: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/163.jpg)
6.5.8��Filter Initialization PhaseThere is a special attribute duet FilterHasInitHandler/FilterInitHandler but it’s leftfor your offline reading.
Stas BekmanInput and Output Filters Slide 163
![Page 164: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/164.jpg)
6.6��All-in-One FilterThe MyApache2::FilterSnoop handler silently snoops onthe data that goes through request and connection filters, inthe input and output modes.
First let’s develop a simple response handler that simplydumps the request’s args and content as strings:
package MyApache2::Dump; use strict; use warnings FATAL => ’all’; use Apache2::RequestRec (); use Apache2::RequestIO (); use Apache2::Filter (); use APR::Brigade ();
Stas BekmanInput and Output Filters Slide 164
![Page 165: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/165.jpg)
use APR::Bucket (); use Apache2::Const -compile => qw(OK M_POST); sub handler { my $r = shift; $r->content_type(’text/plain’); $r->print("args:\n", $r->args, "\n"); if ($r->method_number == Apache2::Const::M_POST) { my $data = content($r); $r->print("content:\n$data\n"); } return Apache2::Const::OK; }
Stas BekmanInput and Output Filters Slide 165
![Page 166: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/166.jpg)
sub content { # see your handouts, the details are unimportant here } 1;
Stas BekmanInput and Output Filters Slide 166
![Page 167: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/167.jpg)
which is configured as:
PerlModule MyApache2::Dump <Location /dump> SetHandler modperl PerlResponseHandler MyApache2::Dump </Location>
Stas BekmanInput and Output Filters Slide 167
![Page 168: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/168.jpg)
If we issue the following request:
% echo "mod_perl rules" | POST ’http://localhost:8002/dump?foo=1&bar=2’
the response will be:
args: foo=1&bar=2 content: mod_perl rules
As you can see it simply dumped the query string and theposted data.
Stas BekmanInput and Output Filters Slide 168
![Page 169: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/169.jpg)
Now let’s write the snooping filter:
package MyApache2::FilterSnoop; use strict; use warnings; use base qw(Apache2::Filter); use Apache2::FilterRec (); use APR::Brigade (); use APR::Bucket (); use APR::BucketType (); use Apache2::Const -compile => qw(OK DECLINED); use APR::Const -compile => ’:common’; sub connection : FilterConnectionHandler { snoop("connection", @_) } sub request : FilterRequestHandler { snoop("request", @_) }
Stas BekmanInput and Output Filters Slide 169
![Page 170: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/170.jpg)
sub snoop { my $type = shift; my($f, $bb, $mode, $block, $readbytes) = @_; # filter args # $mode, $block, $readbytes are passed only for input filters my $stream = defined $mode ? "input" : "output"; # read the data and pass-through the bucket brigades unchanged if (defined $mode) { # input filter my $rv = $f->next->get_brigade($bb, $mode, $block, $readbytes); return $rv unless $rv == APR::Const::SUCCESS; bb_dump($type, $stream, $bb); } else { # output filter bb_dump($type, $stream, $bb); my $rv = $f->next->pass_brigade($bb); return $rv unless $rv == APR::Const::SUCCESS; } return Apache2::Const::OK; }
Stas BekmanInput and Output Filters Slide 170
![Page 171: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/171.jpg)
sub bb_dump { my($type, $stream, $bb) = @_; my @data; for (my $b = $bb->first; $b; $b = $bb->next($b)) { $b->read(my $bdata); push @data, $b->type->name, $bdata; } # send the sniffed info to STDERR so not to interfere with normal # output my $direction = $stream eq ’output’ ? ">>>" : "<<<"; print STDERR "\n$direction $type $stream filter\n"; my $c = 1; while (my($btype, $data) = splice @data, 0, 2) { print STDERR " o bucket $c: $btype\n"; print STDERR "[$data]\n"; $c++; } } 1;
Stas BekmanInput and Output Filters Slide 171
![Page 172: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/172.jpg)
We want to use this somewhat complicated filter to visualizehow various kind of filters work.
Since this module combines several kind of filters it’s the bestto try to understand its implementation after you understandstandalone filters’ implementation.
At this stage what’s important is to see it at work.
Stas BekmanInput and Output Filters Slide 172
![Page 173: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/173.jpg)
Let’s snoop on connection and request filter levels in bothdirections by applying the following configuration:
Listen 8008 <VirtualHost _default_:8008> PerlModule MyApache2::FilterSnoop PerlModule MyApache2::Dump # Connection filters PerlInputFilterHandler MyApache2::FilterSnoop::connection PerlOutputFilterHandler MyApache2::FilterSnoop::connection <Location /dump> SetHandler modperl PerlResponseHandler MyApache2::Dump # Request filters PerlInputFilterHandler MyApache2::FilterSnoop::request PerlOutputFilterHandler MyApache2::FilterSnoop::request </Location> </VirtualHost>
Stas BekmanInput and Output Filters Slide 173
![Page 174: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/174.jpg)
If we issue the following request:
% echo "mod_perl rules" | POST ’http://localhost:8008/dump?foo=1&bar=2’
the response doesn’t get affected by the snooping filter
though we can see all the diagnostics in error_log
Stas BekmanInput and Output Filters Slide 174
![Page 175: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/175.jpg)
First we can see the connection input filter at work, as itprocesses the HTTP headers.
We can see that for this request each header is put into aseparate brigade with a single bucket.
The data is conveniently enclosed by [] so you can see thenew line characters as well.
<<< connection input filter o bucket 1: HEAP [POST /dump?foo=1&bar=2 HTTP/1.1 ] <<< connection input filter o bucket 1: HEAP [TE: deflate,gzip;q=0.3 ]
Stas BekmanInput and Output Filters Slide 175
![Page 176: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/176.jpg)
<<< connection input filter o bucket 1: HEAP [Connection: TE, close ] <<< connection input filter o bucket 1: HEAP [Host: localhost:8008 ] <<< connection input filter o bucket 1: HEAP [User-Agent: lwp-request/2.01 ] <<< connection input filter o bucket 1: HEAP
Stas BekmanInput and Output Filters Slide 176
![Page 177: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/177.jpg)
[Content-Length: 14 ] <<< connection input filter o bucket 1: HEAP [Content-Type: application/x-www-form-urlencoded ] <<< connection input filter o bucket 1: HEAP [ ]
Here the HTTP header has been terminated by a double new line.
Stas BekmanInput and Output Filters Slide 177
![Page 178: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/178.jpg)
So far all the buckets were of the HEAP type, meaning thatthey were allocated from the heap memory.
Notice that the HTTP request input filters will never see thebucket brigades with HTTP headers, as it has been consumed bythe last core connection filter.
Stas BekmanInput and Output Filters Slide 178
![Page 179: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/179.jpg)
The following two entries are generated when MyApache2::Dump::handler reads the POSTed content:
<<< connection input filter o bucket 1: HEAP [mod_perl rules] <<< request input filter o bucket 1: HEAP [mod_perl rules] o bucket 2: EOS []
The connection input filter is run before the request input filter.
Stas BekmanInput and Output Filters Slide 179
![Page 180: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/180.jpg)
Both filters see the same data, since they don’t modify it
The bucket of type EOS indicates the end of stream.
Stas BekmanInput and Output Filters Slide 180
![Page 181: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/181.jpg)
Next we can see that MyApache2::Dump::handler hasgenerated its response.
However only the request output filter is filtering it at this point:
>>> request output filter o bucket 1: TRANSIENT [args: foo=1&bar=2 content: mod_perl rules ]
Stas BekmanInput and Output Filters Slide 181
![Page 182: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/182.jpg)
Next, Apache injects the HTTP headers:
>>> connection output filter o bucket 1: HEAP [HTTP/1.1 200 OK Date: Fri, 04 Jun 2004 09:13:26 GMT Server: Apache/2.0.50-dev (Unix) mod_perl/1.99_15-dev Perl/v5.8.4 mod_ssl/2.0.50-dev OpenSSL/0.9.7c DAV/2 Connection: close Transfer-Encoding: chunked Content-Type: text/plain; charset=ISO-8859-1 ]
Stas BekmanInput and Output Filters Slide 182
![Page 183: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/183.jpg)
the first response body’s brigade inside the connection output filter:
>>> connection output filter o bucket 1: TRANSIENT [2b ] o bucket 2: TRANSIENT [args: foo=1&bar=2 content: mod_perl rules ] o bucket 3: IMMORTAL [ ]
Stas BekmanInput and Output Filters Slide 183
![Page 184: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/184.jpg)
Finally the output is flushed,
to make sure that any buffered output is sent to the client:
>>> connection output filter o bucket 1: IMMORTAL [0 ] o bucket 2: EOS []
Stas BekmanInput and Output Filters Slide 184
![Page 185: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/185.jpg)
This module helps to understand that each filter handler canbe called many time during each request and connection.
It’s called for each bucket brigade.
the HTTP request input filter is called only if there is somePOSTed data to read
If you run the same request without POSTing any data orsimply running a GET request, the request input filter won’t be called.
Stas BekmanInput and Output Filters Slide 185
![Page 186: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/186.jpg)
6.7��Input Filtersmod_perl supports 2 kinds of input filters:
1. Connection input filters
2. HTTP Request input filters
Stas BekmanInput and Output Filters Slide 186
![Page 187: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/187.jpg)
6.7.1��Connection Input FiltersLet’s write a poor man’s s/GET/HEAD/ rewrite handler
The handler looks for the data like:
GET /perl/test.pl HTTP/1.1
and turns it into:
HEAD /perl/test.pl HTTP/1.1
Stas BekmanInput and Output Filters Slide 187
![Page 188: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/188.jpg)
package MyApache2::InputFilterGET2HEAD; # use strict; use warnings; use base qw(Apache2::Filter); use APR::Brigade (); use APR::Bucket (); use Apache2::Const -compile => ’OK’; use APR::Const -compile => ’:common’;
Stas BekmanInput and Output Filters Slide 188
![Page 189: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/189.jpg)
sub handler : FilterConnectionHandler { # my($f, $bb, $mode, $block, $readbytes) = @_; return Apache2::Const::DECLINED if $f->ctx; my $rv = $f->next->get_brigade($bb, $mode, $block, $readbytes); return $rv unless $rv == APR::Const::SUCCESS; for (my $b = $bb->first; $b; $b = $bb->next($b)) { $b->read(my $data); warn("data: $data\n"); if ($data and $data =~ s|^GET|HEAD|) { my $nb = APR::Bucket->new($bb->bucket_alloc, $data); $b->insert_after($nb); $b->remove; # no longer needed $f->ctx(1); # flag that that we have done the job last; } } Apache2::Const::OK; } 1;
Stas BekmanInput and Output Filters Slide 189
![Page 190: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/190.jpg)
For example, consider the following response handler:
package MyApache2::RequestType; # use Apache2::RequestIO (); use Apache2::RequestRec (); use Apache2::Response (); use Apache2::Const -compile => ’OK’; sub handler { my $r = shift; $r->content_type(’text/plain’); my $response = "the request type was " . $r->method; $r->set_content_length(length $response); $r->print($response); Apache2::Const::OK; } 1;
Stas BekmanInput and Output Filters Slide 190
![Page 191: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/191.jpg)
which returns to the client the request type it has issued.
In the case of the HEAD request Apache will discard theresponse body, but it’ll will still set the correct Content-Length header, which will be 24 in case of the GET request and 25 for HEAD.
Stas BekmanInput and Output Filters Slide 191
![Page 192: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/192.jpg)
Therefore if this response handler is configured as:
Listen 8005 <VirtualHost _default_:8005> <Location /> SetHandler modperl PerlResponseHandler +MyApache2::RequestType </Location> </VirtualHost>
and a GET request is issued to /:
panic% perl -MLWP::UserAgent -le \ ’$r = LWP::UserAgent->new()->get("http://localhost:8005/"); \ print $r->headers->content_length . ": ". $r->content’ 24: the request type was GET
Stas BekmanInput and Output Filters Slide 192
![Page 193: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/193.jpg)
where the response’s body is:
the request type was GET
And the Content-Length header is set to 24.
Stas BekmanInput and Output Filters Slide 193
![Page 194: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/194.jpg)
However if we enable the MyApache2::InputFilterGET2HEAD input connection filter:
Listen 8005 <VirtualHost _default_:8005> PerlInputFilterHandler +MyApache2::InputFilterGET2HEAD <Location /> SetHandler modperl PerlResponseHandler +MyApache2::RequestType </Location> </VirtualHost>
And issue the same GET request, we get only:
25:
Stas BekmanInput and Output Filters Slide 194
![Page 195: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/195.jpg)
which means that the body was discarded by Apache,because our filter turned the GET request into a HEAD request.
If Apache wasn’t discarding the body on HEAD, the responsewould be:
the request type was HEAD
that’s why the content length is reported as 25 and not 24 asin the real GET request.
Stas BekmanInput and Output Filters Slide 195
![Page 196: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/196.jpg)
6.7.2��HTTP Request Input FiltersRequest filters are similar to connection filters, but have anaccess to a request object and they don’t see the headers.
Stas BekmanInput and Output Filters Slide 196
![Page 197: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/197.jpg)
6.7.3��Bucket Brigade-based Input Filters
Here is the request input filter that lowercases the request’s body:
package MyApache2::InputRequestFilterLC; # use strict; use warnings; use base qw(Apache2::Filter); use Apache2::Connection (); use APR::Brigade (); use APR::Bucket (); use Apache2::Const -compile => ’OK’; use APR::Const -compile => ’:common’;
Stas BekmanInput and Output Filters Slide 197
![Page 198: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/198.jpg)
sub handler : FilterRequestHandler { my($f, $bb, $mode, $block, $readbytes) = @_; my $c = $f->c; my $bb_ctx = APR::Brigade->new($c->pool, $c->bucket_alloc); my $rv = $f->next->get_brigade($bb_ctx, $mode, $block, $readbytes); return $rv unless $rv == APR::Const::SUCCESS; while (!$bb_ctx->is_empty) { my $b = $bb_ctx->first; if ($b->is_eos) { $bb->insert_tail($b); last; } my $len = $b->read(my $data); $b = APR::Bucket->new($bb->bucket_alloc, lc $data) if $len; $b->remove; $bb->insert_tail($b); }
Stas BekmanInput and Output Filters Slide 198
![Page 199: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/199.jpg)
Apache2::Const::OK; } 1;
Stas BekmanInput and Output Filters Slide 199
![Page 200: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/200.jpg)
the MyApache2::Dump response handler dumps the querystring and the content body as a response
Using the following configuration:
<Location /lc_input> SetHandler modperl PerlResponseHandler +MyApache2::Dump PerlInputFilterHandler +MyApache2::InputRequestFilterLC </Location>
Stas BekmanInput and Output Filters Slide 200
![Page 201: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/201.jpg)
When issuing a POST request:
% echo "mOd_pErl RuLeS" | POST ’http://localhost:8002/lc_input?FoO=1&BAR=2’
we get a response:
args: FoO=1&BAR=2 content: mod_perl rules
Indeed we can see that our filter has lowercased the POSTedbody, before the content handler received it.
The query string didn’t change, since the filter didn’t operateon headers.
Stas BekmanInput and Output Filters Slide 201
![Page 202: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/202.jpg)
6.7.4��Stream-oriented Input Filters package MyApache2::InputRequestFilterLC2; # use base qw(Apache2::Filter); use Apache2::Const -compile => ’OK’; sub handler : FilterRequestHandler { my $f = shift; while ($f->read(my $buffer, 1024)) { $f->print(lc $buffer); } Apache2::Const::OK; } 1;
Stas BekmanInput and Output Filters Slide 202
![Page 203: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/203.jpg)
Configuration:
<Location /lc_input2> SetHandler modperl PerlResponseHandler +MyApache2::Dump PerlInputFilterHandler +MyApache2::InputRequestFilterLC2 </Location>
We get the same results as from using the bucket brigades filter
Stas BekmanInput and Output Filters Slide 203
![Page 204: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/204.jpg)
6.8��Output Filtersmod_perl supports 2 kinds of output filters:
1. Connection input filters
2. HTTP Request input filters
Stas BekmanInput and Output Filters Slide 204
![Page 205: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/205.jpg)
6.8.1��Connection Output FiltersConnection filters are similar to HTTP Request filters,
but can see all the data that is going through the server.
We will concentrate on HTTP request filters
Stas BekmanInput and Output Filters Slide 205
![Page 206: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/206.jpg)
6.8.2��HTTP Request Output Filters
Output filters can be written using the bucket brigadesmanipulation or the simplified stream-oriented interface.
Here is a response handler that send two lines of output in asingle string:
1. numerals: 1234567890
2. the English alphabet
Stas BekmanInput and Output Filters Slide 206
![Page 207: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/207.jpg)
package MyApache2::SendAlphaNum; # use Apache2::RequestRec (); use Apache2::RequestIO (); use Apache2::Const -compile => qw(OK);
sub handler { my $r = shift; $r->content_type(’text/plain’); $r->print(1..9, "0\n"); $r->print(’a’..’z’, "\n"); Apache2::Const::OK; } 1;
Stas BekmanInput and Output Filters Slide 207
![Page 208: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/208.jpg)
The purpose of our request output filter is to reverse everyline of the response, preserving the new line characters intheir places.
Since we want to reverse characters only in the responsebody we will use the HTTP request output filter.
Stas BekmanInput and Output Filters Slide 208
![Page 209: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/209.jpg)
6.8.3��Stream-oriented Output Filter package MyApache2::FilterReverse1; # use Apache2::Filter (); use Apache2::Const -compile => qw(OK); sub handler : FilterRequestHandler { my $f = shift; while ($f->read(my $buffer, 1024)) { for (split "\n", $buffer) { $f->print(scalar reverse $_); $f->print("\n"); } } Apache2::Const::OK; } 1;
Stas BekmanInput and Output Filters Slide 209
![Page 210: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/210.jpg)
Add the following configuration to httpd.conf:
PerlModule MyApache2::FilterReverse1 PerlModule MyApache2::SendAlphaNum <Location /reverse1> SetHandler modperl PerlResponseHandler MyApache2::SendAlphaNum PerlOutputFilterHandler MyApache2::FilterReverse1 </Location>
Stas BekmanInput and Output Filters Slide 210
![Page 211: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/211.jpg)
Now when a request to /reverse1 is made, the responsehandler MyApache2::SendAlphaNum::handler() sends:
1234567890 abcdefghijklmnopqrstuvwxyz
as a response and the output filter handler MyApache2::FilterReverse1::handler reverses thelines, so the client gets:
0987654321 zyxwvutsrqponmlkjihgfedcba
Stas BekmanInput and Output Filters Slide 211
![Page 212: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/212.jpg)
6.8.4��Bucket Brigade-basedOutput Filters
The bucket brigades filtering API implementation:
package MyApache2::FilterReverse2; # use strict; use warnings; use base qw(Apache2::Filter); use APR::Brigade (); use APR::Bucket (); use Apache2::Const -compile => ’OK’; use APR::Const -compile => ’:common’; sub handler : FilterRequestHandler { my($f, $bb) = @_;
Stas BekmanInput and Output Filters Slide 212
![Page 213: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/213.jpg)
my $bb_ctx = APR::Brigade->new($f->c->pool, $f->c->bucket_alloc); # while (!$bb->is_empty) { my $b = $bb->first; $b->remove; if ($b->is_eos) { $bb_ctx->insert_tail($b); last; } if ($b->read(my $data)) { $data = join "", map {scalar(reverse $_), "\n"} split "\n", $data; $b = APR::Bucket->new($bb->bucket_alloc, $data); } $bb_ctx->insert_tail($b); } my $rv = $f->next->pass_brigade($bb_ctx); return $rv unless $rv == APR::Const::SUCCESS; Apache2::Const::OK; } 1;
Stas BekmanInput and Output Filters Slide 213
![Page 214: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/214.jpg)
And the corresponding configuration:
PerlModule MyApache2::FilterReverse2 PerlModule MyApache2::SendAlphaNum <Location /reverse2> SetHandler modperl PerlResponseHandler MyApache2::SendAlphaNum PerlOutputFilterHandler MyApache2::FilterReverse2 </Location>
Stas BekmanInput and Output Filters Slide 214
![Page 215: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/215.jpg)
Now when a request to /reverse2 is made, the client gets:
0987654321 zyxwvutsrqponmlkjihgfedcba
as expected.
Stas BekmanInput and Output Filters Slide 215
![Page 216: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/216.jpg)
Stas BekmanHTTP Handlers Slide 216
![Page 217: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/217.jpg)
7�� HTTP Handlers
Stas BekmanHTTP Handlers Slide 217
![Page 218: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/218.jpg)
7.1��AboutHTTP Request Cycle Phases
PerlPostReadRequestHandler
PerlTransHandler
PerlMapToStorageHandler
PerlHeaderParserHandler
PerlInitHandler
PerlAccessHandler
Stas BekmanHTTP Handlers Slide 218
![Page 219: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/219.jpg)
PerlAuthenHandler
PerlAuthzHandler
PerlTypeHandler
PerlFixupHandler
PerlResponseHandler
PerlLogHandler
PerlCleanupHandler
Stas BekmanHTTP Handlers Slide 219
![Page 220: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/220.jpg)
7.2��HTTP Request Handler Skeleton
All HTTP Request handlers have the following structure:
package MyApache2::MyHandlerName; # load modules that are going to be used use ...; # compile (or import) constants use Apache2::Const -compile => qw(OK); sub handler { my $r = shift; # handler code comes here
Stas BekmanHTTP Handlers Slide 220
![Page 221: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/221.jpg)
return Apache2::Const::OK; # or another status constant } 1;
Stas BekmanHTTP Handlers Slide 221
![Page 222: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/222.jpg)
If the handler is declared as a method handler:
sub handler : method { my($class, $r) = @_;
Stas BekmanHTTP Handlers Slide 222
![Page 223: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/223.jpg)
7.3��HTTP Request Cycle Phases
Almost identical to mod_perl 1.0. The differences are:
new phase: PerlMapToStorageHandler
rename: PerlHandler => PerlResponseHandler
PerlResponseHandler now includes filtering
Here is the HTTP request life cycle in mod_perl 2.0:
Stas BekmanHTTP Handlers Slide 223
![Page 224: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/224.jpg)
Stas BekmanHTTP Handlers Slide 224
![Page 225: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/225.jpg)
an HTTP request is processed by 12 phases:
1. PerlPostReadRequestHandler (PerlInitHandler)
2. PerlTransHandler
3. PerlMapToStorageHandler
4. PerlHeaderParserHandler (PerlInitHandler)
5. PerlAccessHandler
6. PerlAuthenHandler
7. PerlAuthzHandler
Stas BekmanHTTP Handlers Slide 225
![Page 226: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/226.jpg)
8. PerlTypeHandler
9. PerlFixupHandler
10. PerlResponseHandler
11. PerlLogHandler
12. PerlCleanupHandler
Stas BekmanHTTP Handlers Slide 226
![Page 227: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/227.jpg)
7.3.1��PerlPostReadRequestHandler
Stas BekmanHTTP Handlers Slide 227
![Page 228: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/228.jpg)
Stas BekmanHTTP Handlers Slide 228
![Page 229: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/229.jpg)
The post_read_request phase is the first request phase andhappens immediately after the request has been read andHTTP headers were parsed.
This phase is usually used to do processing that must happenonce per request.
For example Apache2::Reload is usually invoked at thisphase to reload modified Perl modules.
Stas BekmanHTTP Handlers Slide 229
![Page 230: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/230.jpg)
The following ModPerl::Registry script prints when thelast time httpd.conf has been modified, compared to the startof the request process time:
use strict; use warnings; use Apache2::ServerUtil (); use Apache2::RequestIO (); use File::Spec::Functions qw(catfile); my $r = shift; $r->content_type(’text/plain’); my $conf_file = catfile Apache2::ServerUtil::server_root, "conf", "httpd.conf"; printf "$conf_file is %0.2f minutes old\n", 60*24*(-M $conf_file);
Stas BekmanHTTP Handlers Slide 230
![Page 231: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/231.jpg)
The script reports incorrect time most of the time
Because -M reports the difference between file’s modificationtime and $^T
Under mod_perl $^T is set when the process starts anddoesn’t change after that.
Solution: Reset $^T on each request
Stas BekmanHTTP Handlers Slide 231
![Page 232: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/232.jpg)
package MyApache2::TimeReset; use strict; use warnings; use Apache2::RequestRec (); use Apache2::Const -compile => ’OK’; sub handler { my $r = shift; $^T = $r->request_time; return Apache2::Const::OK; } 1;
Stas BekmanHTTP Handlers Slide 232
![Page 233: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/233.jpg)
We could do:
$^T = time();
But $r->request_time already stores the request’s starttime, so we get it without performing an additional system call.
Stas BekmanHTTP Handlers Slide 233
![Page 234: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/234.jpg)
To enable it just add to httpd.conf:
PerlPostReadRequestHandler MyApache2::TimeReset
either to the global section, or to the <VirtualHost> section ifyou want this handler to be run only for a specific virtual host.
Stas BekmanHTTP Handlers Slide 234
![Page 235: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/235.jpg)
7.3.2��PerlTransHandler
Stas BekmanHTTP Handlers Slide 235
![Page 236: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/236.jpg)
Stas BekmanHTTP Handlers Slide 236
![Page 237: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/237.jpg)
The translate phase is used to manipulate a request’s URI
If no custom handler is provided, the server’s standardtranslation rules (e.g., Alias directives, mod_rewrite, etc.)will continue to be used.
Also used to modify the URI itself and the request method.
This is also a good place to register new handlers for thefollowing phases based on the URI.
Stas BekmanHTTP Handlers Slide 237
![Page 238: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/238.jpg)
mod_rewrite ala mod_perl:
e.g. if the previously static pages are now autogenerated, and
http://example.com/news/20021031/09/index.html _
is now handled by:
http://example.com/perl/news.pl?date=20021031;id=09;page=index.html
we can keep using the old URI, transparent to news.pl and users
Stas BekmanHTTP Handlers Slide 238
![Page 239: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/239.jpg)
package MyApache2::RewriteURI; use strict; use warnings; use Apache2::RequestRec (); use Apache2::Const -compile => qw(DECLINED); sub handler { my $r = shift; my($date, $id, $page) = $r->uri =~ m|^/news/(\d+)/(\d+)/(.*)|; $r->uri("/perl/news.pl"); $r->args("date=$date;id=$id;page=$page"); return Apache2::Const::DECLINED; } 1;
Stas BekmanHTTP Handlers Slide 239
![Page 240: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/240.jpg)
To configure this module simply add to httpd.conf:
PerlTransHandler +MyApache2::RewriteURI
Stas BekmanHTTP Handlers Slide 240
![Page 241: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/241.jpg)
7.3.3��PerlMapToStorageHandler
Stas BekmanHTTP Handlers Slide 241
![Page 242: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/242.jpg)
Stas BekmanHTTP Handlers Slide 242
![Page 243: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/243.jpg)
The map_to_storage phase is used to translate request’s URIinto a corresponding filename
If no custom handler is provided, the server will try to walk thefilesystem trying to find what file or directory corresponds tothe request’s URI.
most likely you want to shortcut this phase for mod_perl
Stas BekmanHTTP Handlers Slide 243
![Page 244: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/244.jpg)
The Don’t-waste-time handler:
package MyApache2::NoTranslation; # use strict; use warnings FATAL => ’all’; use Apache2::Const -compile => qw(OK); sub handler { my $r = shift; # skip ap_directory_walk stat() calls return Apache2::Const::OK; } 1;
config:
PerlMapToStorageHandler MyApache2::NoTranslation
Stas BekmanHTTP Handlers Slide 244
![Page 245: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/245.jpg)
But this can be done from httpd.conf too!
PerlMapToStorageHandler Apache2::Const::OK
If you haven’t already compiled Apache2::Const::OKelsewhere, you should add:
<Perl> use Apache2::Const -compile => qw(OK); </Perl>
Stas BekmanHTTP Handlers Slide 245
![Page 246: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/246.jpg)
same handler but support TRACE calls
package MyApache2::NoTranslation2; # use strict; use warnings FATAL => ’all’; use Apache2::RequestRec ();
use Apache2::Const -compile => qw(DECLINED OK M_TRACE); sub handler { my $r = shift; return Apache2::Const::DECLINED if $r->method_number == Apache2::Const::M_TRACE; # skip ap_directory_walk stat() calls return Apache2::Const::OK; } 1;
Stas BekmanHTTP Handlers Slide 246
![Page 247: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/247.jpg)
Another way to prevent the core translation:
$r->filename(__FILE__);
this can be done in PerlTransHandler as well
Stas BekmanHTTP Handlers Slide 247
![Page 248: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/248.jpg)
7.3.4��PerlHeaderParserHandler
Stas BekmanHTTP Handlers Slide 248
![Page 249: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/249.jpg)
Stas BekmanHTTP Handlers Slide 249
![Page 250: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/250.jpg)
The header_parser phase is the first phase to happen afterthe request has been mapped to its <Location> (or anequivalent container).
At this phase the handler can examine the request headersand to take a special action based on these.
e.g., this phase can be used to block evil clients targetingcertain resources, while few resources were wasted so far.
Stas BekmanHTTP Handlers Slide 250
![Page 251: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/251.jpg)
Apache handles the HEAD, GET, POST and several otherHTTP methods.
But you can invent your own methods and make Apacheaccept them.
e.g., emails are very similar to HTTP messages: they have aset of headers and a body, sometimes a multi-part body.
MyApache2::SendEmail extends HTTP by adding asupport for the EMAIL method.
It enables the new extension and pushes the real contenthandler during the PerlHeaderParserHandler phase:
<Location /email> PerlHeaderParserHandler MyApache2::SendEmail </Location>
Stas BekmanHTTP Handlers Slide 251
![Page 252: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/252.jpg)
package MyApache2::SendEmail; # use strict; use warnings; use Apache2::RequestRec (); use Apache2::RequestIO (); use Apache2::RequestUtil (); use Apache2::Server (); use Apache2::ServerRec (); use Apache2::Process (); use APR::Table (); use Apache2::Const -compile => qw(DECLINED OK); use constant SMTP_HOSTNAME => "localhost";
Stas BekmanHTTP Handlers Slide 252
![Page 253: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/253.jpg)
sub handler { # my $r = shift; return Apache2::Const::DECLINED unless $r->method eq ’EMAIL’; $r->server->method_register(’EMAIL’); $r->handler("perl-script"); $r->push_handlers(PerlResponseHandler => \&send_email_handler); return Apache2::Const::OK; } sub send_email_handler { # my $r = shift; my %headers = map {$_ => $r->headers_in->get($_)} qw(To From Subject); my $content = content($r); my $status = send_email(\%headers, \$content); $r->content_type(’text/plain’); $r->print($status ? "ACK" : "NACK"); return Apache2::Const::OK; }
Stas BekmanHTTP Handlers Slide 253
![Page 254: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/254.jpg)
sub send_email { # my($rh_headers, $r_body) = @_; require MIME::Lite; MIME::Lite->send("smtp", SMTP_HOSTNAME, Timeout => 60); my $msg = MIME::Lite->new(%$rh_headers, Data => $$r_body); $msg->send; } sub content { # my $r = shift; # unimportant here, see your handouts return $buf; } 1;
Stas BekmanHTTP Handlers Slide 254
![Page 255: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/255.jpg)
when you extend an HTTP protocol you need to have a clientthat knows how to use the extension.
So here is a simple client that uses LWP::UserAgent toissue an EMAIL method request over HTTP protocol:
Stas BekmanHTTP Handlers Slide 255
![Page 256: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/256.jpg)
require LWP::UserAgent; # my $url = "http://localhost:8000/email/"; my %headers = ( From => ’[email protected]’, To => ’[email protected]’, Subject => ’3 weeks in Tibet’, ); my $content = <<EOI; I didn’t have an email software, but could use HTTP so I’m sending it over HTTP EOI my $headers = HTTP::Headers->new(%headers); my $req = HTTP::Request->new("EMAIL", $url, $headers, $content); my $res = LWP::UserAgent->new->request($req); print $res->is_success ? $res->content : "failed";
Stas BekmanHTTP Handlers Slide 256
![Page 257: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/257.jpg)
7.3.5��PerlInitHandler
Stas BekmanHTTP Handlers Slide 257
![Page 258: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/258.jpg)
Stas BekmanHTTP Handlers Slide 258
![Page 259: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/259.jpg)
If configured inside any container directive, except <VirtualHost>, this handler is an alias for PerlHeaderParserHandler.
It is the first handler to be invoked when serving a request.
For example if Apache2::Reload is configured as:
PerlInitHandler Apache2::Reload PerlSetVar ReloadAll Off PerlSetVar ReloadModules "MyApache2::*"
then it will always monitor and reload all MyApache2::*modules that have been modified since the last HTTP request.
Stas BekmanHTTP Handlers Slide 259
![Page 260: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/260.jpg)
However if we move the global configuration into a <Location> container:
<Location /devel> PerlInitHandler Apache2::Reload PerlSetVar ReloadAll Off PerlSetVar ReloadModules "MyApache2::*" SetHandler perl-script PerlResponseHandler ModPerl::Registry Options +ExecCGI </Location>
it acts as an alias for PerlPostReadRequestHandler
therefore Apache2::Reload will reload the modifiedmodules, only when a request to the /devel namespace is made
Stas BekmanHTTP Handlers Slide 260
![Page 261: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/261.jpg)
7.3.6��PerlAccessHandler
Stas BekmanHTTP Handlers Slide 261
![Page 262: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/262.jpg)
Stas BekmanHTTP Handlers Slide 262
![Page 263: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/263.jpg)
The access_checker phase is the first of three handlers thatare involved in what’s known as AAA: Authentication andAuthorization, and Access control.
This phase can be used to restrict access from a certain IPaddress, time of the day or any other rule not connected tothe user’s identity.
Stas BekmanHTTP Handlers Slide 263
![Page 264: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/264.jpg)
The concept behind access checker handler is very simple:
return Apache2::Const::FORBIDDEN if the access isnot allowed,
otherwise return Apache2::Const::OK.
Stas BekmanHTTP Handlers Slide 264
![Page 265: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/265.jpg)
This handler denies requests made from IPs on the blacklist:
package MyApache2::BlockByIP; # use Apache2::RequestRec (); use Apache2::Connection (); use Apache2::Const -compile => qw(FORBIDDEN OK); my %bad_ips = map {$_ => 1} qw(127.0.0.1 10.0.0.4); sub handler { my $r = shift; return exists $bad_ips{$r->connection->remote_ip} ? Apache2::Const::FORBIDDEN : Apache2::Const::OK; } 1;
Stas BekmanHTTP Handlers Slide 265
![Page 266: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/266.jpg)
To enable the handler simply add it to the container thatneeds to be protected.
For example to protect an access to the registry scriptsexecuted from the base location /perl add:
<Location /perl/> SetHandler perl-script PerlResponseHandler ModPerl::Registry PerlAccessHandler MyApache2::BlockByIP Options +ExecCGI </Location>
Stas BekmanHTTP Handlers Slide 266
![Page 267: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/267.jpg)
7.3.7��PerlAuthenHandler
Stas BekmanHTTP Handlers Slide 267
![Page 268: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/268.jpg)
Stas BekmanHTTP Handlers Slide 268
![Page 269: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/269.jpg)
The check_user_id (authen) phase is called whenever therequested file or directory is password protected.
This, in turn, requires that the directory be associated with AuthName, AuthType and at least one require directive.
This phase is usually used to verify a user’s identification credentials.
If the credentials are verified to be correct, the handler shouldreturn Apache2::Const::OK.
to defer the decision: Apache2::Const::DECLINED
Otherwise the handler returns Apache2::Const::HTTP_UNAUTHORIZED to indicate thatthe user has not authenticated successfully.
Stas BekmanHTTP Handlers Slide 269
![Page 270: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/270.jpg)
When Apache sends the HTTP header with this code, thebrowser will normally pop up a dialog box that prompts the user forlogin information.
The following example handler verifies that:
SECRET_LENGTH == length join " ", $username, $password;
Stas BekmanHTTP Handlers Slide 270
![Page 271: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/271.jpg)
package MyApache2::SecretLengthAuth; # use Apache2::Access (); use Apache2::RequestUtil (); use Apache2::Const -compile => qw(OK DECLINED HTTP_UNAUTHORIZED); use constant SECRET_LENGTH => 14; sub handler { my $r = shift; my ($status, $password) = $r->get_basic_auth_pw; return $status unless $status == Apache2::Const::OK; return Apache2::Const::OK if SECRET_LENGTH == length join " ", $r->user, $password; $r->note_basic_auth_failure; return Apache2::Const::HTTP_UNAUTHORIZED; } 1;
Stas BekmanHTTP Handlers Slide 271
![Page 272: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/272.jpg)
To enable this handler you have to tell Apache:
what authentication scheme to use (AuthType: Basicor Digest)
what’s the authentication realm (AuthName: any string)
the Require directive is needed to specify whichusernames are allowed to authenticate. If you set it to valid-user any username will do.
Stas BekmanHTTP Handlers Slide 272
![Page 273: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/273.jpg)
<Location /perl/> SetHandler perl-script PerlResponseHandler ModPerl::Registry PerlAuthenHandler MyApache2::SecretLengthAuth Options +ExecCGI AuthType Basic AuthName "The Gate" Require valid-user </Location>
Stas BekmanHTTP Handlers Slide 273
![Page 274: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/274.jpg)
7.3.8��PerlAuthzHandler
Stas BekmanHTTP Handlers Slide 274
![Page 275: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/275.jpg)
Stas BekmanHTTP Handlers Slide 275
![Page 276: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/276.jpg)
The auth_checker (authz) phase is used for authorization control.
This phase requires a successful authentication from theprevious phase, because a username is needed in order todecide whether a user is authorized to access the requested resource.
As this phase is tightly connected to the authentication phase,the handlers registered for this phase are only called whenthe requested resource is password protected, similar to theauth phase.
The handler is expected to return:
Apache2::Const::DECLINED to defer the decision,
Stas BekmanHTTP Handlers Slide 276
![Page 277: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/277.jpg)
Apache2::Const::OK to indicate its acceptance of theuser’s authorization,
or Apache2::Const::HTTP_UNAUTHORIZED toindicate that the user is not authorized to access the requested document.
Stas BekmanHTTP Handlers Slide 277
![Page 278: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/278.jpg)
The MyApache2::SecretResourceAuthz handler grantsaccess to certain resources only to certain users who havealready properly authenticated:
package MyApache2::SecretResourceAuthz; # use strict; use warnings; use Apache2::Access (); use Apache2::RequestUtil (); use Apache2::Const -compile => qw(OK HTTP_UNAUTHORIZED); my %protected = ( ’admin’ => [’stas’], ’report’ => [qw(stas boss)], );
Stas BekmanHTTP Handlers Slide 278
![Page 279: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/279.jpg)
sub handler { # my $r = shift; my $user = $r->user; if ($user) { my($section) = $r->uri =~ m|^/company/(\w+)/|; if (defined $section && exists $protected{$section}) { my $users = $protected{$section}; return Apache2::Const::OK if grep { $_ eq $user } @$users; } else { return Apache2::Const::OK; } } $r->note_basic_auth_failure; return Apache2::Const::HTTP_UNAUTHORIZED; } 1;
Stas BekmanHTTP Handlers Slide 279
![Page 280: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/280.jpg)
The configuration is similar to PerlAuthenHandler, thistime we just add the PerlAuthzHandler setting. The restdoesn’t change.
Alias /company/ /home/httpd/httpd-2.0/perl/ <Location /company/> SetHandler perl-script PerlResponseHandler ModPerl::Registry PerlAuthenHandler MyApache2::SecretLengthAuth PerlAuthzHandler MyApache2::SecretResourceAuthz Options +ExecCGI AuthType Basic AuthName "The Secret Gate" Require valid-user </Location>
Stas BekmanHTTP Handlers Slide 280
![Page 281: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/281.jpg)
7.3.9��PerlTypeHandler
Stas BekmanHTTP Handlers Slide 281
![Page 282: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/282.jpg)
Stas BekmanHTTP Handlers Slide 282
![Page 283: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/283.jpg)
The type_checker phase is used to set the response MIMEtype (Content-type) and sometimes other bits of documenttype information like the document language.
e.g., mod_autoindex, which performs automatic directoryindexing, uses this phase to map the filename extensions tothe corresponding icons which will be later used in the listingof files.
Of course later phases may override the mime type set in this phase.
When overriding the default type_checker handler, which isusually the mod_mime handler, don’t forget to set theresponse handler:
Stas BekmanHTTP Handlers Slide 283
![Page 284: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/284.jpg)
$r->handler(’perl-script’); # or $r->handler(’modperl’); $r->set_handlers(PerlResponseHandler => \&handler);
It’s the easiest to leave this stage alone and do any desiredsettings in the fixups phase.
Stas BekmanHTTP Handlers Slide 284
![Page 285: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/285.jpg)
7.3.10��PerlFixupHandler
Stas BekmanHTTP Handlers Slide 285
![Page 286: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/286.jpg)
Stas BekmanHTTP Handlers Slide 286
![Page 287: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/287.jpg)
The fixups phase is happening just before the contenthandling phase.
It gives the last chance to do things before the response is generated.
For example in this phase mod_env populates theenvironment with variables configured with SetEnv and PassEnv directives.
Stas BekmanHTTP Handlers Slide 287
![Page 288: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/288.jpg)
This fixup handler tells Apache at run time which handler andcallback should be used to process the request based on thefile extension of the request’s URI.
package MyApache2::FileExtDispatch; # use strict; use warnings; use Apache2::RequestIO (); use Apache2::RequestRec (); use Apache2::RequestUtil (); use Apache2::Const -compile => ’OK’; use constant HANDLER => 0; use constant CALLBACK => 1; my %exts = ( cgi => [’perl-script’, \&cgi_handler], pl => [’modperl’, \&pl_handler ], tt => [’perl-script’, \&tt_handler ], txt => [’default-handler’, undef ], );
Stas BekmanHTTP Handlers Slide 288
![Page 289: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/289.jpg)
sub handler { # my $r = shift; my($ext) = $r->uri =~ /\.(\w+)$/; $ext = ’txt’ unless defined $ext and exists $exts{$ext}; $r->handler($exts{$ext}->[HANDLER]); if (defined $exts{$ext}->[CALLBACK]) { $r->set_handlers(PerlResponseHandler => $exts{$ext}->[CALLBACK]); } return Apache2::Const::OK; }
Stas BekmanHTTP Handlers Slide 289
![Page 290: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/290.jpg)
sub cgi_handler { content_handler($_[0], ’cgi’) } sub pl_handler { content_handler($_[0], ’pl’) } sub tt_handler { content_handler($_[0], ’tt’) } sub content_handler { # my($r, $type) = @_; $r->content_type(’text/plain’); $r->print("A handler of type ’$type’ was called"); return Apache2::Const::OK; } 1;
Stas BekmanHTTP Handlers Slide 290
![Page 291: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/291.jpg)
Here is how this handler is configured:
Alias /dispatch/ /home/httpd/httpd-2.0/htdocs/ <Location /dispatch/> PerlFixupHandler MyApache2::FileExtDispatch </Location>
Notice that there is no need to specify anything, but the fixup handler.
It applies the rest of the settings dynamically at run-time.
Stas BekmanHTTP Handlers Slide 291
![Page 292: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/292.jpg)
7.3.11��PerlResponseHandler
Stas BekmanHTTP Handlers Slide 292
![Page 293: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/293.jpg)
Stas BekmanHTTP Handlers Slide 293
![Page 294: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/294.jpg)
The handler (response) phase is used for generating the response.
This is arguably the most important phase and most of theexisting Apache modules do most of their work at this phase.
This is the only phase that requires two directives under mod_perl:
<Location /perl> SetHandler perl-script PerlResponseHandler MyApache2::WorldDomination </Location>
SetHandler set to perl-script or modperl tells Apachethat mod_perl is going to handle the response generation.
Stas BekmanHTTP Handlers Slide 294
![Page 295: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/295.jpg)
PerlResponseHandler tells mod_perl which callback isgoing to do the job.
Stas BekmanHTTP Handlers Slide 295
![Page 296: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/296.jpg)
This handler prints itself:
package MyApache2::Deparse; use strict; use warnings; use Apache2::RequestRec (); use Apache2::RequestIO (); use B::Deparse (); use Apache2::Const -compile => ’OK’; sub handler { my $r = shift; $r->content_type(’text/plain’); $r->print(’sub handler ’, B::Deparse->new->coderef2text(\&handler)); return Apache2::Const::OK; } 1;
Stas BekmanHTTP Handlers Slide 296
![Page 297: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/297.jpg)
To enable this handler add to httpd.conf:
<Location /deparse> SetHandler modperl PerlResponseHandler MyApache2::Deparse </Location>
Stas BekmanHTTP Handlers Slide 297
![Page 298: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/298.jpg)
Now when the server is restarted and we issue a request to http://localhost/deparse we get the following response:
sub handler { package MyApache2::Deparse; use warnings; use strict ’refs’; my $r = shift @_; $r->content_type(’text/plain’); $r->print(’sub handler ’, ’B::Deparse’->new->coderef2text(\&handler)); return 0; }
If you compare it to the source code, it’s pretty much thesame code. B::Deparse is fun to play with!
Stas BekmanHTTP Handlers Slide 298
![Page 299: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/299.jpg)
7.3.12��PerlLogHandler
Stas BekmanHTTP Handlers Slide 299
![Page 300: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/300.jpg)
Stas BekmanHTTP Handlers Slide 300
![Page 301: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/301.jpg)
The log_transaction phase is always executed.
Even if the previous phases were aborted.
At this phase log handlers usually log various informationabout the request and the response.
Stas BekmanHTTP Handlers Slide 301
![Page 302: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/302.jpg)
The following handler logs the request data into user-specific files.
We assume that all URIs include the username in the form of: /~username/
package MyApache2::LogPerUser; # use strict; use warnings; use Apache2::RequestRec (); use Apache2::Connection (); use Fcntl qw(:flock); use File::Spec::Functions qw(catfile); use Apache2::Const -compile => qw(OK DECLINED);
Stas BekmanHTTP Handlers Slide 302
![Page 303: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/303.jpg)
sub handler { # my $r = shift; my($username) = $r->uri =~ m|^/~([^/]+)|; return Apache2::Const::DECLINED unless defined $username; my $entry = sprintf qq(%s [%s] "%s" %d %d\n), $r->connection->remote_ip, scalar(localtime), $r->uri, $r->status, $r->bytes_sent; my $log_path = catfile Apache2::ServerUtil::server_root, "logs", "$username.log"; open my $fh, ">>$log_path" or die "can’t open $log_path: $!"; flock $fh, LOCK_EX; print $fh $entry; close $fh; return Apache2::Const::OK; } 1;
Stas BekmanHTTP Handlers Slide 303
![Page 304: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/304.jpg)
Configuration:
<LocationMatch "^/~"> SetHandler perl-script PerlResponseHandler ModPerl::Registry PerlLogHandler MyApache2::LogPerUser Options +ExecCGI </LocationMatch>
Stas BekmanHTTP Handlers Slide 304
![Page 305: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/305.jpg)
After restarting the server and issuing requests to thefollowing URIs:
http://localhost/~stas/test.pl http://localhost/~eric/test.pl http://localhost/~stas/date.pl
The MyApache2::LogPerUser handler will append to logs/stas.log:
127.0.0.1 [Sat Aug 31 01:50:38 2002] "/~stas/test.pl" 200 8 127.0.0.1 [Sat Aug 31 01:50:40 2002] "/~stas/date.pl" 200 44
and to logs/eric.log:
127.0.0.1 [Sat Aug 31 01:50:39 2002] "/~eric/test.pl" 200 8
Stas BekmanHTTP Handlers Slide 305
![Page 306: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/306.jpg)
7.3.13��PerlCleanupHandler
Stas BekmanHTTP Handlers Slide 306
![Page 307: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/307.jpg)
Stas BekmanHTTP Handlers Slide 307
![Page 308: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/308.jpg)
There is no cleanup Apache phase,
It’s a mod_perl convenience invention
It runs immediately after the request has been served
and before the request object is destroyed.
Used to run cleanup code
or to do some time consuming work after the client has gone
Stas BekmanHTTP Handlers Slide 308
![Page 309: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/309.jpg)
Usage:
a cleanup() callback accepts $r as its only argument.
PerlCleanupHandler MyApache2::Cleanup
or:
$r->push_handlers(PerlCleanupHandler => \&cleanup);
a cleanup() callback accepts an optional arbitrary argument
$r->pool->cleanup_register(\&cleanup, $arg);
Stas BekmanHTTP Handlers Slide 309
![Page 310: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/310.jpg)
Example: delete a temporary file in the cleanup handler
package MyApache2::Cleanup1; # use strict; use warnings FATAL => ’all’; use File::Spec::Functions qw(catfile); use Apache2::RequestRec (); use Apache2::RequestIO (); use Apache2::RequestUtil (); use Apache2::Const -compile => qw(OK DECLINED); use APR::Const -compile => ’SUCCESS’; my $file = catfile "/tmp", "data";
Stas BekmanHTTP Handlers Slide 310
![Page 311: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/311.jpg)
sub handler { # my $r = shift; $r->content_type(’text/plain’); local @ENV{qw(PATH BASH_ENV)}; qx(/bin/ls -l > $file); my $status = $r->sendfile($file); die "sendfile has failed" unless $status == APR::Const::SUCCESS; $r->push_handlers(PerlCleanupHandler => \&cleanup); return Apache2::Const::OK; } sub cleanup { my $r = shift; die "Can’t find file: $file" unless -e $file; unlink $file or die "failed to unlink $file"; return Apache2::Const::OK; } 1;
Stas BekmanHTTP Handlers Slide 311
![Page 312: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/312.jpg)
Next we add the following configuration:
<Location /cleanup1> SetHandler modperl PerlResponseHandler MyApache2::Cleanup1 </Location>
Now when requesting /cleanup1
the contents of the current directory will be printed
and once the request is over the temporary file is deleted.
Stas BekmanHTTP Handlers Slide 312
![Page 313: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/313.jpg)
The problem in Multi-processes/threads env
MyApache2::Cleanup1 is problematic for it uses the same filename
Better use a unique filename ($$ + APR::OS::current_thread_id())
Even better, use a non-predictable name: rand, APR::UUID
But how do we pass the filename to the cleanup handler?
MyApache2::Cleanup2 solves the problem with:
$r->pool->cleanup_register(\&cleanup, $file);
Stas BekmanHTTP Handlers Slide 313
![Page 314: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/314.jpg)
package MyApache2::Cleanup2; # use strict; use warnings FATAL => ’all’; use File::Spec::Functions qw(catfile); use Apache2::RequestRec (); use Apache2::RequestIO (); use Apache2::RequestUtil (); use APR::UUID (); use APR::Pool (); use Apache2::Const -compile => qw(OK DECLINED); use APR::Const -compile => ’SUCCESS’; my $file_base = catfile "/tmp", "data-";
Stas BekmanHTTP Handlers Slide 314
![Page 315: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/315.jpg)
sub handler { # my $r = shift; $r->content_type(’text/plain’); my $file = $file_base . APR::UUID->new->format; local @ENV{qw(PATH BASH_ENV)}; qx(/bin/ls -l > $file); my $status = $r->sendfile($file); die "sendfile has failed" unless $status == APR::Const::SUCCESS; $r->pool->cleanup_register(\&cleanup, $file); return Apache2::Const::OK; } sub cleanup { my $file = shift; die "Can’t find file: $file" unless -e $file; unlink $file or die "failed to unlink $file"; return Apache2::Const::OK; } 1;
Stas BekmanHTTP Handlers Slide 315
![Page 316: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/316.jpg)
Similarly to the first handler, we add the configuration:
<Location /cleanup2> SetHandler modperl PerlResponseHandler MyApache2::Cleanup2 </Location>
Stas BekmanHTTP Handlers Slide 316
![Page 317: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/317.jpg)
Stas Bekmanmod_perl 1.0 to mod_perl 2.0 Migration Slide 317
![Page 318: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/318.jpg)
8�� mod_perl 1.0 tomod_perl 2.0 Migration
Stas Bekmanmod_perl 1.0 to mod_perl 2.0 Migration Slide 318
![Page 319: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/319.jpg)
8.1��AboutConfiguration Directives Changes
mod_perl API Changes
mod_perl Modules Changes
Stas Bekmanmod_perl 1.0 to mod_perl 2.0 Migration Slide 319
![Page 320: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/320.jpg)
8.2��Migrating from mod_perl1.0 to mod_perl 2.0
Some configuration directives were renamed or removed
Several APIs have changed, renamed, removed, or moved tonew packages.
...
But there is a back-compatibility layer!
Stas Bekmanmod_perl 1.0 to mod_perl 2.0 Migration Slide 320
![Page 321: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/321.jpg)
8.3��The Shortest MigrationPath from 1.0 use Apache2::compat;
Certain Configuration directives and APIs have changed
See http://perl.apache.org/docs/2.0/user/compat/compat.html
Stas Bekmanmod_perl 1.0 to mod_perl 2.0 Migration Slide 321
![Page 322: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/322.jpg)
8.4��Migrating Configuration Files
Several configuration directives are deprecated in 2.0
but still available for backwards compatibility
Otherwise, consider using the directives that have replaced them.
Stas Bekmanmod_perl 1.0 to mod_perl 2.0 Migration Slide 322
![Page 323: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/323.jpg)
8.4.1��PerlHandler PerlHandler => PerlResponseHandler
Stas Bekmanmod_perl 1.0 to mod_perl 2.0 Migration Slide 323
![Page 324: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/324.jpg)
8.4.2��PerlSendHeader PerlSendHeader On => PerlOptions +ParseHeaders PerlSendHeader Off => PerlOptions -ParseHeaders
Stas Bekmanmod_perl 1.0 to mod_perl 2.0 Migration Slide 324
![Page 325: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/325.jpg)
8.4.3��PerlSetupEnv PerlSetupEnv On => PerlOptions +SetupEnv PerlSetupEnv Off => PerlOptions -SetupEnv
Stas Bekmanmod_perl 1.0 to mod_perl 2.0 Migration Slide 325
![Page 326: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/326.jpg)
8.4.4��PerlTaintCheckThe taint mode now can be turned on with:
PerlSwitches -T
It’s disabled by default.
You cannot disable it once it’s enabled.
Stas Bekmanmod_perl 1.0 to mod_perl 2.0 Migration Slide 326
![Page 327: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/327.jpg)
8.4.5��PerlWarnWarnings now can be enabled globally with:
PerlSwitches -w
Stas Bekmanmod_perl 1.0 to mod_perl 2.0 Migration Slide 327
![Page 328: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/328.jpg)
8.4.6��PerlFreshRestartPerlFreshRestart is a mod_perl 1.0 legacy
In mod_perl 2.0 a full tear-down and startup of interpreters isdone on restart.
To reuse the same httpd.conf for 1.0 and 2.0:
<IfDefine !MODPERL2> PerlFreshRestart </IfDefine>
Stas Bekmanmod_perl 1.0 to mod_perl 2.0 Migration Slide 328
![Page 329: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/329.jpg)
8.5��Code PortingCertain APIs couldn’t be preserved in 2.0, hence:
use Apache2::compat;
which is slower, because it’s implemented in Perl.
it’s also incomplete, since some APIs can’t be backported
Consider getting rid of using the compat layer
Stas Bekmanmod_perl 1.0 to mod_perl 2.0 Migration Slide 329
![Page 330: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/330.jpg)
8.5.1��Finding Which ModulesNeed To Be LoadedThe Poison:
$r->content_type(’text/plain’); $r->print("Hello cruel world!");
the execution fails with:
can’t find method ’content_type’ ...
One has to load modules containing mod_perl methodsbefore they can be used
Stas Bekmanmod_perl 1.0 to mod_perl 2.0 Migration Slide 330
![Page 331: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/331.jpg)
The Remedy:
% perl -MModPerl::MethodLookup -e print_method content_type to use method ’content_type’ add: use Apache2::RequestRec ();
Alias:
# c-style shell % alias lookup "perl -MModPerl::MethodLookup -e print_method" # bash-style shell % alias lookup="perl -MModPerl::MethodLookup -e print_method" % lookup content_type to use method ’content_type’ add: use Apache2::RequestRec ();
Stas Bekmanmod_perl 1.0 to mod_perl 2.0 Migration Slide 331
![Page 332: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/332.jpg)
8.6��ModPerl::Registry Familys/Apache::Registry/ModPerl::Registry/
Alias /perl/ /home/httpd/perl/ <Location /perl> SetHandler perl-script PerlResponseHandler ModPerl::Registry Options +ExecCGI PerlOptions +ParseHeaders </Location>
MPM doesn’t matter, mp2 should work the same everywhere
Issues with chdir(), which affects all threads: use ModPerl::RegistryPrefork or ModPerl::PerlRunPrefork
Stas Bekmanmod_perl 1.0 to mod_perl 2.0 Migration Slide 332
![Page 333: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/333.jpg)
Cook your own registry with ModPerl::RegistryCooker
is-a: Subclass one of the classes
has-a: Build your own using aliasing
Stas Bekmanmod_perl 1.0 to mod_perl 2.0 Migration Slide 333
![Page 334: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/334.jpg)
8.7��Method Handlers$$ doesn’t work since some callbacks accepts more than 2 args
package Bird; @ISA = qw(Eagle); sub handler : method { my($class, $r) = @_; ...; }
See the attributes manpage.
Stas Bekmanmod_perl 1.0 to mod_perl 2.0 Migration Slide 334
![Page 335: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/335.jpg)
8.8��Apache::StatINC Replacement
Replace:
PerlInitHandler Apache::StatINC
with:
PerlInitHandler Apache2::Reload
Apache2::Reload provides an extra functionality
See the module’s manpage.
Stas Bekmanmod_perl 1.0 to mod_perl 2.0 Migration Slide 335
![Page 336: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/336.jpg)
Stas BekmanThat’s all folks! Slide 336
![Page 337: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/337.jpg)
9�� That’s all folks!
Stas BekmanThat’s all folks! Slide 337
![Page 338: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/338.jpg)
9.1��ThanksThanks to TicketMaster for sponsoring my work on mod_perl
Stas BekmanThat’s all folks! Slide 338
![Page 339: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/339.jpg)
9.2��Referencesmod_perl 2.0 information can be found at:
http://perl.apache.org/docs/2.0/
Further Questions?
Grab me at the corridor and demand answers
Ask at [email protected]
Stas BekmanThat’s all folks! Slide 339
![Page 340: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/340.jpg)
9.3��A Shameless Plug
Stas BekmanThat’s all folks! Slide 340
![Page 341: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/341.jpg)
Stas BekmanThat’s all folks! Slide 341
![Page 342: Mod Perl 2.0 Tutorial Slides.pdf](https://reader031.vdocuments.us/reader031/viewer/2022013108/553266724a795998578b45b8/html5/thumbnails/342.jpg)
Now available under Creative Commons license:
download
modify
distribute
sell
etc.
Get it from http://modperlbook.org/
Stas BekmanThat’s all folks! Slide 342