Download presentation
Presentation is loading. Please wait.
1
(Brief) Introduction to mod_perl
Geoffrey Young
3
Overview Apache 101 mod_perl 101 specific mod_perl examples
4
Apache's Pre-fork Model
5
Apache's Pre-fork Model
Apache uses a pre-fork architecture
6
Apache's Pre-fork Model
Apache uses a pre-fork architecture httpd (parent)
7
Apache's Pre-fork Model
Apache uses a pre-fork architecture httpd (parent) httpd (child) httpd (child) httpd (child) httpd (child)
8
Nice, Responsible Children
9
Nice, Responsible Children
httpd child processes are responsible for serving the incoming requests, not the parent
10
Nice, Responsible Children
httpd child processes are responsible for serving the incoming requests, not the parent each child processes one incoming request at a time
11
Nice, Responsible Children
httpd child processes are responsible for serving the incoming requests, not the parent each child processes one incoming request at a time when the request is over the child is free to serve the next request
12
Request Phases
13
Request Phases Apache breaks down request processing into separate, logical parts called phases
14
Request Phases Apache breaks down request processing into separate, logical parts called phases each request is stepped through the phases until...
15
Request Phases Apache breaks down request processing into separate, logical parts called phases each request is stepped through the phases until... all processing is complete somebody throws an "error"
16
Request Phases Apache breaks down request processing into separate, logical parts called phases each request is stepped through the phases until... all processing is complete somebody throws an "error" developers are given the chance to hook into each phase to add custom processing
17
Apache Request Cycle client request
18
Apache Request Cycle client request GET /perl-status HTTP/1.1
Accept: text/html, image/png, image/jpeg, image/gif, image/x-xbitmap, */* Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0 Accept-Language: en Cache-Control: no-cache Connection: Keep-Alive, TE Host: User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000) Opera [en]
19
Apache Request Cycle client request GET /perl-status HTTP/1.1
Accept: text/html, image/png, image/jpeg, image/gif, image/x-xbitmap, */* Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0 Accept-Language: en Cache-Control: no-cache Connection: Keep-Alive, TE Host: User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000) Opera [en]
20
Apache Request Cycle client request GET /perl-status HTTP/1.1
Accept: text/html, image/png, image/jpeg, image/gif, image/x-xbitmap, */* Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0 Accept-Language: en Cache-Control: no-cache Connection: Keep-Alive, TE Host: User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000) Opera [en]
21
Apache Request Cycle client request
22
Apache Request Cycle client request URI-based init
23
Apache Request Cycle client request URI-based init URI translation
24
Apache Request Cycle client request URI-based init URI translation
file-based init
25
Apache Request Cycle client request URI-based init URI translation
file-based init resource control
26
Apache Request Cycle client request URI-based init URI translation
file-based init MIME setting resource control
27
Apache Request Cycle client request URI-based init URI translation
fixups file-based init MIME setting resource control
28
Apache Request Cycle client request URI-based init content
URI translation fixups file-based init MIME setting resource control
29
Apache Request Cycle content HTTP/1.1 200 OK
Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: text/html
30
Apache Request Cycle content HTTP/1.1 200 OK
Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: text/html
31
Apache Request Cycle content HTTP/1.1 200 OK
Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: text/html
32
Apache Request Cycle client request URI-based init content
URI translation fixups file-based init MIME setting resource control
33
Apache Request Cycle client request logging URI-based init content
URI translation fixups file-based init MIME setting resource control
34
Apache Request Cycle client request logging URI-based init content
URI translation fixups file-based init MIME setting resource control
35
So What?
36
So What? most Apache users don't worry about the request cycle too much...
37
So What? most Apache users don't worry about the request cycle too much... ...but they do use modules that plug into it
38
...for instance Resource control
39
...for instance Resource control mod_auth:
AuthUserFile access/.htpasswd
40
...for instance Resource control URI Translation mod_auth:
AuthUserFile access/.htpasswd URI Translation
41
...for instance Resource control URI Translation mod_auth:
AuthUserFile access/.htpasswd URI Translation mod_rewrite: RewriteRule /favicon.ico$ /images/favicon.ico
42
...for instance Resource control URI Translation Content Generation
mod_auth: AuthUserFile access/.htpasswd URI Translation mod_rewrite: RewriteRule /favicon.ico$ /images/favicon.ico Content Generation
43
...for instance Resource control URI Translation Content Generation
mod_auth: AuthUserFile access/.htpasswd URI Translation mod_rewrite: RewriteRule /favicon.ico$ /images/favicon.ico Content Generation mod_cgi: SetHandler cgi-script
44
That's great breaking down the request into distinct phases has many benefits
45
That's great breaking down the request into distinct phases has many benefits gives each processing point a role that can be easily managed and programmed
46
That's great breaking down the request into distinct phases has many benefits gives each processing point a role that can be easily managed and programmed makes Apache more like an application framework rather than a content engine
47
That's great, but... breaking down the request into distinct phases has many benefits gives each processing point a role that can be easily managed and programmed makes Apache more like an application framework rather than a content engine but you have to code in C
48
Enter mod_perl
49
Enter mod_perl mod_perl offers an interface to each phase of the request cycle
50
Enter mod_perl mod_perl offers an interface to each phase of the request cycle opens up the Apache API to Perl code
51
Enter mod_perl mod_perl offers an interface to each phase of the request cycle opens up the Apache API to Perl code allows you to program targeted parts of the request cycle using Perl
52
Enter mod_perl mod_perl offers an interface to each phase of the request cycle opens up the Apache API to Perl code allows you to program targeted parts of the request cycle using Perl we like Perl
53
Apache Request Cycle client request logging URI-based init content
URI translation fixups file-based init MIME setting resource control
54
mod_perl Interface client request PerlCleanupHandler PerlLogHandler
PerlPostReadRequestHandler logging URI-based init PerlHandler PerlTransHandler content URI translation PerlFixupHandler PerlHeaderParserHandler fixups file-based init PerlAccessHandler PerlAuthenHandler PerlAuthzHandler PerlTypeHandler MIME setting resource control
55
mod_perl Interface world's ugliest slide client request
PerlCleanupHandler PerlLogHandler PerlPostReadRequestHandler world's ugliest slide logging URI-based init PerlHandler PerlTransHandler content URI translation PerlFixupHandler PerlHeaderParserHandler fixups file-based init PerlAccessHandler PerlAuthenHandler PerlAuthzHandler PerlTypeHandler MIME setting resource control
56
How?
57
How? mod_perl embeds an entire perl interpreter into Apache
58
How? mod_perl embeds an entire perl interpreter into Apache
each httpd child has its own perl interpreter
59
Why?
60
Why? create a persistent perl environment
61
Why? create a persistent perl environment increase performace
62
Why? create a persistent perl environment
increase performace* (for the dynamic parts)
63
Why? create a persistent perl environment open up the Apache API
increase performace* (for the dynamic parts) open up the Apache API
64
Why? create a persistent perl environment open up the Apache API
increase performace* (for the dynamic parts) open up the Apache API increase developer options
65
Why? create a persistent perl environment open up the Apache API
increase performace* (for the dynamic parts) open up the Apache API increase developer options because it's cool
66
What is mod_perl?
67
What is mod_perl? to the masses, mod_perl is just faster CGI a la Apache::Registry
68
What is mod_perl? to the masses, mod_perl is just faster CGI a la Apache::Registry leads to comparisons to FastCGI, PerlEx, and other CGI enhancement engines
69
What is mod_perl? to the masses, mod_perl is just faster CGI a la Apache::Registry leads to comparisons to FastCGI, PerlEx, and other CGI enhancement engines not an accurate description of mod_perl, so comparisons aren't really valid
70
Registry is just a Handler
Apache::Registry is merely an (incredibly clever and amazing) mod_perl handler
71
Registry is just a Handler
Apache::Registry is merely an (incredibly clever and amazing) mod_perl handler uses the mod_perl API to interface with the content generation phase of the request cycle
72
Registry is just a Handler
Apache::Registry is merely an (incredibly clever and amazing) mod_perl handler uses the mod_perl API to interface with the content generation phase of the request cycle possible because of what mod_perl really is
73
What is mod_perl?
74
What is mod_perl? a C extension module, just like mod_cgi or mod_rewrite
75
What is mod_perl? a C extension module, just like mod_cgi or mod_rewrite the Perl interface to the Apache API
76
What is mod_perl? a C extension module, just like mod_cgi or mod_rewrite the Perl interface to the Apache API allows you to interact and alter the server directly
77
What is mod_perl? a C extension module, just like mod_cgi or mod_rewrite the Perl interface to the Apache API allows you to interact and alter the server directly gives you the ability to "program within Apache's framework instead of around it"
78
What's the Big Deal?
79
What's the Big Deal? mod_perl allows you to intercept basic Apache functions and replace them with your own (sometimes devious) Perl substitutes
80
What's the Big Deal? mod_perl allows you to intercept basic Apache functions and replace them with your own (sometimes devious) Perl substitutes extremely powerful
81
What's the Big Deal? mod_perl allows you to intercept basic Apache functions and replace them with your own (sometimes devious) Perl substitutes extremely powerful interesting side effects
82
mod_cgi Setup Alias /cgi-bin/ /usr/local/apache/cgi-bin/
<Location /cgi-bin> SetHandler cgi-script Options +ExecCGI Order Allow,Deny Allow from All </Location>
83
mod_cgi Setup Alias /cgi-bin/ /usr/local/apache/cgi-bin/
<Location /cgi-bin> SetHandler cgi-script Options +ExecCGI Order Allow,Deny Allow from All </Location>
84
Apache::Registry Setup Alias /perl-bin/ /usr/local/apache/perl-bin/
<Location /perl-bin> SetHandler perl-script PerlHandler Apache::Registry Options +ExecCGI Order Allow,Deny Allow from All </Location>
85
Apache::Registry Setup Alias /perl-bin/ /usr/local/apache/perl-bin/
<Location /perl-bin> SetHandler perl-script PerlHandler Apache::Registry Options +ExecCGI Order Allow,Deny Allow from All </Location>
86
Apache::Registry Client
87
Apache::Registry Client http://localhost/perl-bin/foo.pl
88
Apache::Registry Client Server http://localhost/perl-bin/foo.pl
89
Apache::Registry Client Server http://localhost/perl-bin/foo.pl
mod_perl intercepts content generation
90
Apache::Registry Client Server http://localhost/perl-bin/foo.pl
mod_perl intercepts content generation for Apache/Registry.pm
91
Apache::Registry Client Server http://localhost/perl-bin/foo.pl
mod_perl intercepts content generation for Apache/Registry.pm calls Apache::Registry::handler(Apache->request)
92
Apache::Registry Client Server http://localhost/perl-bin/foo.pl
mod_perl intercepts content generation for Apache/Registry.pm calls Apache::Registry::handler(Apache->request) inserts wizardry
93
Apache::Registry Client Server http://localhost/perl-bin/foo.pl
mod_perl intercepts content generation for Apache/Registry.pm calls Apache::Registry::handler(Apache->request) inserts wizardry returns response to client
94
Wizardry, you say?
95
Wizardry, you say? the wizardry is basically just putting the CGI script into it's own package
96
Wizardry, you say? the wizardry is basically just putting the CGI script into it's own package package Apache::ROOT::perl_2dbin::foo_2epl; sub handler { BEGIN { $^W = 1; }; ... your script here... } 1;
97
Wizardry, you say? the wizardry is basically just putting the CGI script into it's own package package Apache::ROOT::perl_2dbin::foo_2epl; sub handler { BEGIN { $^W = 1; }; ... your script here... } 1; because the perl interpreter is persistent the (compiled) package is already in memory when called
98
So, how fast is it?
99
So, how fast is it?
100
So, how fast is it? ab -n1000 -c100 2 requests per second (650 seconds for test to run)
101
So, how fast is it? ab -n1000 -c100 2 requests per second (650 seconds for test to run) ab -n1000 -c100 34 requests per second (30 seconds for test to run)
102
So, how fast is it? ab -n1000 -c100 2 requests per second (650 seconds for test to run) ab -n1000 -c100 34 requests per second (30 seconds for test to run) ab -n1000 -c100 55 requests per second (18 seconds for test to run)
104
"The dream is always the same"
105
"The dream is always the same"
the basic process for mod_perl is the same for content generation as for the other request phases
106
"The dream is always the same"
the basic process for mod_perl is the same for content generation as for the other request phases Apache passes control to mod_perl
107
"The dream is always the same"
the basic process for mod_perl is the same for content generation as for the other request phases Apache passes control to mod_perl mod_perl passes control to your Perl subroutine
108
"The dream is always the same"
the basic process for mod_perl is the same for content generation as for the other request phases Apache passes control to mod_perl mod_perl passes control to your Perl subroutine your Perl subroutine defines the status
109
"The dream is always the same"
the basic process for mod_perl is the same for content generation as for the other request phases Apache passes control to mod_perl mod_perl passes control to your Perl subroutine your Perl subroutine defines the status mod_perl passes status back to Apache
110
"The dream is always the same"
the basic process for mod_perl is the same for content generation as for the other request phases Apache passes control to mod_perl mod_perl passes control to your Perl subroutine your Perl subroutine defines the status mod_perl passes status back to Apache Apache continues along
111
Apache Logging
112
Apache Logging default logging mechanism in Apache
113
Apache Logging default logging mechanism in Apache configuration
LogFormat "%h %l %u %t \"%r\" %>s %b" common CustomLog logs/access_log common
114
Apache Logging default logging mechanism in Apache configuration
LogFormat "%h %l %u %t \"%r\" %>s %b" common CustomLog logs/access_log common result [22/Apr/2002:11:28: ] "GET /perl-status HTTP/1.1"
115
Apache Logging default logging mechanism in Apache
configuration LogFormat "%h %l %u %t \"%r\" %>s %b" common CustomLog logs/access_log common result [22/Apr/2002:11:28: ] "GET /perl-status HTTP/1.1" we can accomplish the same thing using the mod_perl API
116
Caveats just an illustration
117
Caveats just an illustration
in general, we don't duplicate default functionality even though we can
118
Caveats just an illustration
in general, we don't duplicate default functionality even though we can core Apache routines are faster
119
Caveats just an illustration
in general, we don't duplicate default functionality even though we can core Apache routines are faster have been around longer
120
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = shift; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
121
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = shift; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
122
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = shift; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
123
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = shift; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
124
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = shift; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
125
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = shift; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
126
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = Apache->request; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
127
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = shift; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
128
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = shift; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
129
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = shift; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
130
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = shift; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
131
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = shift; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
132
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = shift; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
133
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = shift; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
134
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = shift; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
135
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = shift; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
136
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = shift; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
137
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = shift; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
138
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = shift; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
139
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = shift; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
140
package My::CommonLog; use Apache::Constants qw(OK SERVER_ERROR);
use Apache::File; use Apache::Util qw(ht_time); use strict; sub handler { my $r = shift; my $c = $r->connection; my $log = $r->server_root_relative("logs/access_log"); my $fh = Apache::File->new(">>$log") or return SERVER_ERROR; = ($r->get_remote_host, $c->remote_logname, $r->user, ht_time($r->request_time, '[%d/%b/%Y:%H:%M:%S %z]', 0), (join '', '"', $r->the_request, '"'), $r->last->status, $r->bytes_sent); @line = map { $_ ||= '-' print $fh (join ' "\n"; return OK; } 1;
141
Setup add CommonLog.pm
142
Setup add CommonLog.pm to @INC ServerRoot/lib/perl/My/CommonLog.pm
143
Setup add CommonLog.pm to @INC add to httpd.conf
ServerRoot/lib/perl/My/CommonLog.pm add to httpd.conf
144
Setup add CommonLog.pm to @INC add to httpd.conf
ServerRoot/lib/perl/My/CommonLog.pm add to httpd.conf PerlModule My::CommonLog PerlLogHandler My::CommonLog
145
Setup add CommonLog.pm to @INC add to httpd.conf that's it!
ServerRoot/lib/perl/My/CommonLog.pm add to httpd.conf PerlModule My::CommonLog PerlLogHandler My::CommonLog that's it!
146
Key Concept the Apache request object, $r
147
Key Concept the Apache request object, $r
passed to handlers or available via Apache->request()
148
Key Concept the Apache request object, $r
passed to handlers or available via Apache->request() provides access to the Apache class, which provides access to the request attributes
149
Key Concept the Apache request object, $r
passed to handlers or available via Apache->request() provides access to the Apache class, which provides access to the request attributes singleton-like constructor
151
Just the Beginning
152
Just the Beginning almost every part of Apache's default behavior can be replaced, rewritten, or extended using mod_perl
153
Just the Beginning almost every part of Apache's default behavior can be replaced, rewritten, or extended using mod_perl in many cases you can do much more than you can with Apache and C due to Perl's ability to fold, spindle, and mutilate everyday items
154
User Authentication
155
User Authentication Apache default authentication mechansim is mod_auth
156
User Authentication Apache default authentication mechansim is mod_auth uses a password file generated using Apache's htpasswd utility
157
User Authentication Apache default authentication mechansim is mod_auth uses a password file generated using Apache's htpasswd utility geoff:zzpEyL0tbgwwk
158
User Authentication configuration placed in .htaccess file or httpd.conf
159
User Authentication configuration placed in .htaccess file or httpd.conf AuthUserFile access/.htpasswd AuthName "my site" AuthType Basic Require valid-user
160
User Authentication configuration placed in .htaccess file or httpd.conf AuthUserFile access/.htpasswd AuthName "my site" AuthType Basic Require valid-user
161
Who Uses Flat Files? flat files are limiting, hard to manage, difficult to integrate, and just plain boring
162
Who Uses Flat Files? flat files are limiting, hard to manage, difficult to integrate, and just plain boring we can use the Apache API and Perl to replace flat files with our own authentication mechanism
163
How Authentication Works
client requests a document
164
How Authentication Works
client requests a document GET /perl-status HTTP/1.1 Accept: text/xml, image/png, image/jpeg, image/gif, text/plain Accept-Charset: ISO , utf-8;q=0.66, *;q=0.66 Accept-Encoding: gzip, deflate, compress;q=0.9 Accept-Language: en-us Connection: keep-alive Host: Keep-Alive: 300 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US)
165
How Authentication Works
client requests a document GET /perl-status HTTP/1.1 Accept: text/xml, image/png, image/jpeg, image/gif, text/plain Accept-Charset: ISO , utf-8;q=0.66, *;q=0.66 Accept-Encoding: gzip, deflate, compress;q=0.9 Accept-Language: en-us Connection: keep-alive Host: Keep-Alive: 300 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US) server denies request
166
How Authentication Works
client requests a document GET /perl-status HTTP/1.1 Accept: text/xml, image/png, image/jpeg, image/gif, text/plain Accept-Charset: ISO , utf-8;q=0.66, *;q=0.66 Accept-Encoding: gzip, deflate, compress;q=0.9 Accept-Language: en-us Connection: keep-alive Host: Keep-Alive: 300 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US) server denies request HTTP/ Authorization Required WWW-Authenticate: Basic realm="my site" Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: text/html; charset=iso
167
How Authentication Works
client requests a document GET /perl-status HTTP/1.1 Accept: text/xml, image/png, image/jpeg, image/gif, text/plain Accept-Charset: ISO , utf-8;q=0.66, *;q=0.66 Accept-Encoding: gzip, deflate, compress;q=0.9 Accept-Language: en-us Connection: keep-alive Host: Keep-Alive: 300 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US) server denies request HTTP/ Authorization Required WWW-Authenticate: Basic realm="my site" Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: text/html; charset=iso
168
How Authentication Works
client request client request logging URI-based init content URI translation fixups file-based init MIME setting resource control
169
How Authentication Works
client request client request URI-based init URI translation file-based init resource control resource control
170
How Authentication Works
client request client request URI-based init URI translation file-based init resource control resource control HTTP/ Authorization Required
171
How Authentication Works
client request client request logging URI-based init URI translation file-based init resource control resource control HTTP/ Authorization Required
172
How Authentication Works
client sends a new request
173
How Authentication Works
client sends a new request GET /perl-status HTTP/1.1 Accept: text/xml, image/png, image/jpeg, image/gif, text/plain Accept-Charset: ISO , utf-8;q=0.66, *;q=0.66 Accept-Encoding: gzip, deflate, compress;q=0.9 Accept-Language: en-us Authorization: Basic Z2VvZmY6YWZha2VwYXNzd29yZA== Connection: keep-alive Host: Keep-Alive: 300 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US)
174
How Authentication Works
client sends a new request GET /perl-status HTTP/1.1 Accept: text/xml, image/png, image/jpeg, image/gif, text/plain Accept-Charset: ISO , utf-8;q=0.66, *;q=0.66 Accept-Encoding: gzip, deflate, compress;q=0.9 Accept-Language: en-us Authorization: Basic Z2VvZmY6YWZha2VwYXNzd29yZA== Connection: keep-alive Host: Keep-Alive: 300 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US)
175
How Authentication Works
client sends a new request GET /perl-status HTTP/1.1 Accept: text/xml, image/png, image/jpeg, image/gif, text/plain Accept-Charset: ISO , utf-8;q=0.66, *;q=0.66 Accept-Encoding: gzip, deflate, compress;q=0.9 Accept-Language: en-us Authorization: Basic Z2VvZmY6YWZha2VwYXNzd29yZA== Connection: keep-alive Host: Keep-Alive: 300 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US) server sends document
176
How Authentication Works
client sends a new request GET /perl-status HTTP/1.1 Accept: text/xml, image/png, image/jpeg, image/gif, text/plain Accept-Charset: ISO , utf-8;q=0.66, *;q=0.66 Accept-Encoding: gzip, deflate, compress;q=0.9 Accept-Language: en-us Authorization: Basic Z2VvZmY6YWZha2VwYXNzd29yZA== Connection: keep-alive Host: Keep-Alive: 300 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US) server sends document HTTP/ OK Keep-Alive: timeout=15, max=99 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: text/html
177
Do it in Perl since mod_perl gives us the ability to intercept the request cycle before Apache, we can authenticate using Perl instead
178
Do it in Perl since mod_perl gives us the ability to intercept the request cycle before Apache, we can authenticate using Perl instead Apache provides an API, making the job easy
179
Do it in Perl since mod_perl gives us the ability to intercept the request cycle before Apache, we can authenticate using Perl instead Apache provides an API, making the job easy mod_perl provides access to the Apache API
180
package My::Authenticate;
use Apache::Constants qw(OK DECLINED AUTH_REQUIRED); use strict; sub handler { my $r = shift; # Let subrequests pass. return DECLINED unless $r->is_initial_req; # Get the client-supplied credentials. my ($status, $password) = $r->get_basic_auth_pw; return $status unless $status == OK; # Perform some custom user/password validation. return OK if authenticate_user($r->user, $password); # Whoops, bad credentials. $r->note_basic_auth_failure; return AUTH_REQUIRED; }
181
package My::Authenticate;
use Apache::Constants qw(OK DECLINED AUTH_REQUIRED); use strict; sub handler { my $r = shift; # Let subrequests pass. return DECLINED unless $r->is_initial_req; # Get the client-supplied credentials. my ($status, $password) = $r->get_basic_auth_pw; return $status unless $status == OK; # Perform some custom user/password validation. return OK if authenticate_user($r->user, $password); # Whoops, bad credentials. $r->note_basic_auth_failure; return AUTH_REQUIRED; }
182
package My::Authenticate;
use Apache::Constants qw(OK DECLINED AUTH_REQUIRED); use strict; sub handler { my $r = shift; # Let subrequests pass. return DECLINED unless $r->is_initial_req; # Get the client-supplied credentials. my ($status, $password) = $r->get_basic_auth_pw; return $status unless $status == OK; # Perform some custom user/password validation. return OK if authenticate_user($r->user, $password); # Whoops, bad credentials. $r->note_basic_auth_failure; return AUTH_REQUIRED; }
183
package My::Authenticate;
use Apache::Constants qw(OK DECLINED AUTH_REQUIRED); use strict; sub handler { my $r = shift; # Let subrequests pass. return DECLINED unless $r->is_initial_req; # Get the client-supplied credentials. my ($status, $password) = $r->get_basic_auth_pw; return $status unless $status == OK; # Perform some custom user/password validation. return OK if authenticate_user($r->user, $password); # Whoops, bad credentials. $r->note_basic_auth_failure; return AUTH_REQUIRED; }
184
package My::Authenticate;
use Apache::Constants qw(OK DECLINED AUTH_REQUIRED); use strict; sub handler { my $r = shift; # Let subrequests pass. return DECLINED unless $r->is_initial_req; # Get the client-supplied credentials. my ($status, $password) = $r->get_basic_auth_pw; return $status unless $status == OK; # Perform some custom user/password validation. return OK if authenticate_user($r->user, $password); # Whoops, bad credentials. $r->note_basic_auth_failure; return AUTH_REQUIRED; }
185
package My::Authenticate;
use Apache::Constants qw(OK DECLINED AUTH_REQUIRED); use strict; sub handler { my $r = shift; # Let subrequests pass. return DECLINED unless $r->is_initial_req; # Get the client-supplied credentials. my ($status, $password) = $r->get_basic_auth_pw; return $status unless $status == OK; # Perform some custom user/password validation. return OK if authenticate_user($r->user, $password); # Whoops, bad credentials. $r->note_basic_auth_failure; return AUTH_REQUIRED; }
186
package My::Authenticate;
use Apache::Constants qw(OK DECLINED AUTH_REQUIRED); use strict; sub handler { my $r = shift; # Let subrequests pass. return DECLINED unless $r->is_initial_req; # Get the client-supplied credentials. my ($status, $password) = $r->get_basic_auth_pw; return $status unless $status == OK; # Perform some custom user/password validation. return OK if authenticate_user($r->user, $password); # Whoops, bad credentials. $r->note_basic_auth_failure; return AUTH_REQUIRED; }
187
package My::Authenticate;
use Apache::Constants qw(OK DECLINED AUTH_REQUIRED); use strict; sub handler { my $r = shift; # Let subrequests pass. return DECLINED unless $r->is_initial_req; # Get the client-supplied credentials. my ($status, $password) = $r->get_basic_auth_pw; return $status unless $status == OK; # Perform some custom user/password validation. return OK if authenticate_user($r->user, $password); # Whoops, bad credentials. $r->note_basic_auth_failure; return AUTH_REQUIRED; }
188
package My::Authenticate;
use Apache::Constants qw(OK DECLINED AUTH_REQUIRED); use strict; sub handler { my $r = shift; # Let subrequests pass. return DECLINED unless $r->is_initial_req; # Get the client-supplied credentials. my ($status, $password) = $r->get_basic_auth_pw; return $status unless $status == OK; # Perform some custom user/password validation. return OK if authenticate_user($r->user, $password); # Whoops, bad credentials. $r->note_basic_auth_failure; return AUTH_REQUIRED; }
189
package My::Authenticate;
use Apache::Constants qw(OK DECLINED AUTH_REQUIRED); use strict; sub handler { my $r = shift; # Let subrequests pass. return DECLINED unless $r->is_initial_req; # Get the client-supplied credentials. my ($status, $password) = $r->get_basic_auth_pw; return $status unless $status == OK; # Perform some custom user/password validation. return OK if authenticate_user($r->user, $password); # Whoops, bad credentials. $r->note_basic_auth_failure; return AUTH_REQUIRED; }
190
package My::Authenticate;
use Apache::Constants qw(OK DECLINED AUTH_REQUIRED); use strict; sub handler { my $r = shift; # Let subrequests pass. return DECLINED unless $r->is_initial_req; # Get the client-supplied credentials. my ($status, $password) = $r->get_basic_auth_pw; return $status unless $status == OK; # Perform some custom user/password validation. return OK if authenticate_user($r->user, $password); # Whoops, bad credentials. $r->note_basic_auth_failure; return AUTH_REQUIRED; }
191
package My::Authenticate;
use Apache::Constants qw(OK DECLINED AUTH_REQUIRED); use strict; sub handler { my $r = shift; # Let subrequests pass. return DECLINED unless $r->is_initial_req; # Get the client-supplied credentials. my ($status, $password) = $r->get_basic_auth_pw; return $status unless $status == OK; # Perform some custom user/password validation. return OK if authenticate_user($r->user, $password); # Whoops, bad credentials. $r->note_basic_auth_failure; return AUTH_REQUIRED; }
192
Configuration change AuthUserFile restricted/.htpasswd
AuthName "my site" AuthType Basic Require valid-user
193
Configuration change to AuthUserFile restricted/.htpasswd
AuthName "my site" AuthType Basic Require valid-user to PerlAuthenHandler My::Authenticate
194
Configuration change to AuthUserFile restricted/.htpasswd
AuthName "my site" AuthType Basic Require valid-user to PerlAuthenHandler My::Authenticate
195
The Choice is Yours how you decide to authenticate is now up to you
196
The Choice is Yours how you decide to authenticate is now up to you
sub authenticate_user { my ($user, $pass) return 1 if $user eq $pass; }
197
The Choice is Yours how you decide to authenticate is now up to you
sub authenticate_user { my ($user, $pass) return 1 if $user eq $pass; } are you seeing the possibilities yet?
198
The Power of CPAN over 25 Apache:: shrink-wrapped modules on CPAN for authentication SecureID Radius SMB LDAP NTLM
199
To Infinity and Beyond!
200
To Infinity and Beyond!
201
To Infinity and Beyond! this example only covered Basic authentication via popup box
202
To Infinity and Beyond! this example only covered Basic authentication via popup box the same techniques can be used to authenticate via a login form plus cookies, munged URLs, or hidden fields
203
To Infinity and Beyond! this example only covered Basic authentication via popup box the same techniques can be used to authenticate via a login form plus cookies, munged URLs, or hidden fields extended to use Digest authentication as well
205
Magic
206
Magic filtered content generation impossible with Apache 1.3
207
Magic filtered content generation impossible with Apache 1.3
can't send CGI output through mod_ssi
208
Magic filtered content generation impossible with Apache 1.3
can't send CGI output through mod_ssi reason for output filters in Apache 2.0
209
Magic filtered content generation impossible with Apache 1.3
can't send CGI output through mod_ssi reason for output filters in Apache 2.0 mod_perl has had output filtering for years
210
Magic filtered content generation impossible with Apache 1.3
can't send CGI output through mod_ssi reason for output filters in Apache 2.0 mod_perl has had output filtering for years possible due to Perl's TIEHANDLE interface
211
TIEHANDLE in mod_perl mod_perl tie()s STDOUT to the Apache class prior to the content generation phase
212
TIEHANDLE in mod_perl mod_perl tie()s STDOUT to the Apache class prior to the content generation phase you can tie() STDOUT as well and override mod_perl's default behavior
213
TIEHANDLE in mod_perl mod_perl tie()s STDOUT to the Apache class prior to the content generation phase you can tie() STDOUT as well and override mod_perl's default behavior very useful with stacked handlers
214
Stacked Handlers
215
Stacked Handlers for each phase of the request, mod_perl will run any registered Perl handlers for that phase
216
Stacked Handlers for each phase of the request, mod_perl will run any registered Perl handlers for that phase you can register more than one Perl handler per phase
217
Stacked Handlers for each phase of the request, mod_perl will run any registered Perl handlers for that phase you can register more than one Perl handler per phase whether all handlers are called depends on the syntax of the phase itself in Apache
218
Stacked Handlers some phase run until the handler list is exhausted
219
Stacked Handlers some phase run until the handler list is exhausted
PerlLogHandler My::DBLogger PerlLogHandler My::FileLogger
220
Stacked Handlers some phase run until the handler list is exhausted
PerlLogHandler My::DBLogger PerlLogHandler My::FileLogger some phases run until one handler returns OK
221
Stacked Handlers some phase run until the handler list is exhausted
PerlLogHandler My::DBLogger PerlLogHandler My::FileLogger some phases run until one handler returns OK PerlTransHandler My::TranslateHTML PerlTransHandler My::TranslateText
222
Stacked Handlers some phase run until the handler list is exhausted
PerlLogHandler My::DBLogger PerlLogHandler My::FileLogger some phases run until one handler returns OK PerlTransHandler My::TranslateHTML PerlTransHandler My::TranslateText all phases terminate on "error"
223
Stacked Content Handlers
for the content generation phase, running multiple Perl handlers can be incredibly powerful
224
Stacked Content Handlers
for the content generation phase, running multiple Perl handlers can be incredibly powerful Apache::Filter implements a simple interface for pipelining content handlers
225
Stacked Content Handlers
for the content generation phase, running multiple Perl handlers can be incredibly powerful Apache::Filter implements a simple interface for pipelining content handlers uses TIEHANDLE in the background
226
Sample PerlHandler create a handler that uses CPAN module HTML::Clean to "clean" outgoing documents
227
Sample PerlHandler create a handler that uses CPAN module HTML::Clean to "clean" outgoing documents alter the handler to use Apache::Filter so that the "clean" output can be passed to other Perl handlers
228
use Apache::Constants qw(OK DECLINED); use Apache::File;
package My::Clean; use Apache::Constants qw(OK DECLINED); use Apache::File; use HTML::Clean; use strict; sub handler { my $r = shift; return DECLINED unless ($r->content_type eq 'text/html'); my $fh = Apache::File->new($r->filename) or return DECLINED; my $dirty = do {local $/; <$fh>}; my $h = HTML::Clean->new(\$dirty); $h->level(3); $h->strip; $r->send_http_header('text/html'); print ${$h->data}; return OK; } 1;
229
use Apache::Constants qw(OK DECLINED); use Apache::File;
package My::Clean; use Apache::Constants qw(OK DECLINED); use Apache::File; use HTML::Clean; use strict; sub handler { my $r = shift; return DECLINED unless ($r->content_type eq 'text/html'); my $fh = Apache::File->new($r->filename) or return DECLINED; my $dirty = do {local $/; <$fh>}; my $h = HTML::Clean->new(\$dirty); $h->level(3); $h->strip; $r->send_http_header('text/html'); print ${$h->data}; return OK; } 1;
230
use Apache::Constants qw(OK DECLINED); use Apache::File;
package My::Clean; use Apache::Constants qw(OK DECLINED); use Apache::File; use HTML::Clean; use strict; sub handler { my $r = shift; return DECLINED unless ($r->content_type eq 'text/html'); my $fh = Apache::File->new($r->filename) or return DECLINED; my $dirty = do {local $/; <$fh>}; my $h = HTML::Clean->new(\$dirty); $h->level(3); $h->strip; $r->send_http_header('text/html'); print ${$h->data}; return OK; } 1;
231
use Apache::Constants qw(OK DECLINED); use Apache::File;
package My::Clean; use Apache::Constants qw(OK DECLINED); use Apache::File; use HTML::Clean; use strict; sub handler { my $r = shift; return DECLINED unless ($r->content_type eq 'text/html'); my $fh = Apache::File->new($r->filename) or return DECLINED; my $dirty = do {local $/; <$fh>}; my $h = HTML::Clean->new(\$dirty); $h->level(3); $h->strip; $r->send_http_header('text/html'); print ${$h->data}; return OK; } 1;
232
use Apache::Constants qw(OK DECLINED); use Apache::File;
package My::Clean; use Apache::Constants qw(OK DECLINED); use Apache::File; use HTML::Clean; use strict; sub handler { my $r = shift; return DECLINED unless ($r->content_type eq 'text/html'); my $fh = Apache::File->new($r->filename) or return DECLINED; my $dirty = do {local $/; <$fh>}; my $h = HTML::Clean->new(\$dirty); $h->level(3); $h->strip; $r->send_http_header('text/html'); print ${$h->data}; return OK; } 1;
233
use Apache::Constants qw(OK DECLINED); use Apache::File;
package My::Clean; use Apache::Constants qw(OK DECLINED); use Apache::File; use HTML::Clean; use strict; sub handler { my $r = shift; return DECLINED unless ($r->content_type eq 'text/html'); my $fh = Apache::File->new($r->filename) or return DECLINED; my $dirty = do {local $/; <$fh>}; my $h = HTML::Clean->new(\$dirty); $h->level(3); $h->strip; $r->send_http_header('text/html'); print ${$h->data}; return OK; } 1;
234
use Apache::Constants qw(OK DECLINED); use Apache::File;
package My::Clean; use Apache::Constants qw(OK DECLINED); use Apache::File; use HTML::Clean; use strict; sub handler { my $r = shift; return DECLINED unless ($r->content_type eq 'text/html'); my $fh = Apache::File->new($r->filename) or return DECLINED; my $dirty = do {local $/; <$fh>}; my $h = HTML::Clean->new(\$dirty); $h->level(3); $h->strip; $r->send_http_header('text/html'); print ${$h->data}; return OK; } 1;
235
use Apache::Constants qw(OK DECLINED); use Apache::File;
package My::Clean; use Apache::Constants qw(OK DECLINED); use Apache::File; use HTML::Clean; use strict; sub handler { my $r = shift; return DECLINED unless ($r->content_type eq 'text/html'); my $fh = Apache::File->new($r->filename) or return DECLINED; my $dirty = do {local $/; <$fh>}; my $h = HTML::Clean->new(\$dirty); $h->level(3); $h->strip; $r->send_http_header('text/html'); print ${$h->data}; return OK; } 1;
236
use Apache::Constants qw(OK DECLINED); use Apache::File;
package My::Clean; use Apache::Constants qw(OK DECLINED); use Apache::File; use HTML::Clean; use strict; sub handler { my $r = shift; return DECLINED unless ($r->content_type eq 'text/html'); my $fh = Apache::File->new($r->filename) or return DECLINED; my $dirty = do {local $/; <$fh>}; my $h = HTML::Clean->new(\$dirty); $h->level(3); $h->strip; $r->send_http_header('text/html'); print ${$h->data}; return OK; } 1;
237
use Apache::Constants qw(OK DECLINED); use Apache::File;
package My::Clean; use Apache::Constants qw(OK DECLINED); use Apache::File; use HTML::Clean; use strict; sub handler { my $r = shift; return DECLINED unless ($r->content_type eq 'text/html'); my $fh = Apache::File->new($r->filename) or return DECLINED; my $dirty = do {local $/; <$fh>}; my $h = HTML::Clean->new(\$dirty); $h->level(3); $h->strip; $r->send_http_header('text/html'); print ${$h->data}; return OK; } 1;
238
use Apache::Constants qw(OK DECLINED); use Apache::File;
package My::Clean; use Apache::Constants qw(OK DECLINED); use Apache::File; use HTML::Clean; use strict; sub handler { my $r = shift; return DECLINED unless ($r->content_type eq 'text/html'); my $fh = Apache::File->new($r->filename) or return DECLINED; my $dirty = do {local $/; <$fh>}; my $h = HTML::Clean->new(\$dirty); $h->level(3); $h->strip; $r->send_http_header('text/html'); print ${$h->data}; return OK; } 1;
239
use Apache::Constants qw(OK DECLINED); use Apache::File;
package My::Clean; use Apache::Constants qw(OK DECLINED); use Apache::File; use HTML::Clean; use strict; sub handler { my $r = shift; return DECLINED unless ($r->content_type eq 'text/html'); my $fh = Apache::File->new($r->filename) or return DECLINED; my $dirty = do {local $/; <$fh>}; my $h = HTML::Clean->new(\$dirty); $h->level(3); $h->strip; $r->send_http_header('text/html'); print ${$h->data}; return OK; } 1;
240
Configuration add directives to httpd.conf to mirror DocumentRoot
Alias /clean /usr/local/apache/htdocs <Location /clean> SetHandler perl-script PerlHandler My::Clean </Location>
241
Results original: 202 bytes <html> <body>
<form method="GET" action="/foo"> Text: <input type="text" name="foo"><br> <input type="submit"> </form> <strong>hi there </strong> </body> </html>
242
Results original: 202 bytes clean: 145 bytes <html> <body>
<form method="GET" action="/foo"> Text: <input type="text" name="foo"><br> <input type="submit"> </form> <strong>hi there </strong> </body> </html> clean: 145 bytes <html><body><form method="GET" action="/foo"> Text: <input type="text" name="foo"><br><input type="submit"></form><b>hi there </b></body></html>
243
Results original: 202 bytes clean: 145 bytes <html> <body>
<form method="GET" action="/foo"> Text: <input type="text" name="foo"><br> <input type="submit"> </form> <strong>hi there </strong> </body> </html> clean: 145 bytes <html><body><form method="GET" action="/foo"> Text: <input type="text" name="foo"><br><input type="submit"></form><b>hi there </b></body></html>
244
Now for the Fun Part
245
Now for the Fun Part modify our handler to work either standalone or as part of a handler chain
246
Now for the Fun Part modify our handler to work either standalone or as part of a handler chain easy using Apache::Filter
247
Apache::Filter Changes
my $fh = Apache::File->new($r->filename) or return DECLINED;
248
Apache::Filter Changes
my $fh = Apache::File->new($r->filename) or return DECLINED; to: my $fh = undef; if (lc $r->dir_config('Filter') eq 'on') { $r = $r->filter_register; ($fh, my $status) = $r->filter_input; return $status unless $status == OK } else { $fh = Apache::File->new($r->filename) or return DECLINED;
249
Apache::Filter Changes
my $fh = Apache::File->new($r->filename) or return DECLINED; to: my $fh = undef; if (lc $r->dir_config('Filter') eq 'on') { $r = $r->filter_register; ($fh, my $status) = $r->filter_input; return $status unless $status == OK } else { $fh = Apache::File->new($r->filename) or return DECLINED;
250
Apache::Filter Changes
my $fh = Apache::File->new($r->filename) or return DECLINED; to: my $fh = undef; if (lc $r->dir_config('Filter') eq 'on') { $r = $r->filter_register; ($fh, my $status) = $r->filter_input; return $status unless $status == OK } else { $fh = Apache::File->new($r->filename) or return DECLINED;
251
Apache::Filter Changes
my $fh = Apache::File->new($r->filename) or return DECLINED; to: my $fh = undef; if (lc $r->dir_config('Filter') eq 'on') { $r = $r->filter_register; ($fh, my $status) = $r->filter_input; return $status unless $status == OK } else { $fh = Apache::File->new($r->filename) or return DECLINED;
252
Apache::Filter Changes
my $fh = Apache::File->new($r->filename) or return DECLINED; to: my $fh = undef; if (lc $r->dir_config('Filter') eq 'on') { $r = $r->filter_register; ($fh, my $status) = $r->filter_input; return $status unless $status == OK } else { $fh = Apache::File->new($r->filename) or return DECLINED;
253
Apache::Filter Changes
my $fh = Apache::File->new($r->filename) or return DECLINED; to: my $fh = undef; if (lc $r->dir_config('Filter') eq 'on') { $r = $r->filter_register; ($fh, my $status) = $r->filter_input; return $status unless $status == OK } else { $fh = Apache::File->new($r->filename) or return DECLINED;
254
Configuration change Alias /clean /usr/local/apache/htdocs
<Location /clean> SetHandler perl-script PerlHandler My::Clean </Location>
255
Configuration change to Alias /clean /usr/local/apache/htdocs
<Location /clean> SetHandler perl-script PerlHandler My::Clean </Location> to PerlModule Apache::Filter PerlSetVar Filter On
256
Configuration change to Alias /clean /usr/local/apache/htdocs
<Location /clean> SetHandler perl-script PerlHandler My::Clean </Location> to PerlModule Apache::Filter PerlSetVar Filter On
257
So What?
258
So What? new Apache::Filter aware code works the same as the standalone module
259
So What? new Apache::Filter aware code works the same as the standalone module can be used as part of a PerlHandler chain
260
So What? new Apache::Filter aware code works the same as the standalone module can be used as part of a PerlHandler chain can be any part of the chain
261
Compressing Output Apache::Compress
262
Compressing Output Apache::Compress available from CPAN
uses Compress::Zlib to compress output Apache::Filter aware
263
Configuration change Alias /clean /usr/local/apache/htdocs
<Location /clean> SetHandler perl-script PerlHandler My::Clean PerlSetVar Filter On </Location>
264
Configuration change to Alias /clean /usr/local/apache/htdocs
<Location /clean> SetHandler perl-script PerlHandler My::Clean PerlSetVar Filter On </Location> to PerlHandler My::Clean Apache::Compress
265
Configuration change to Alias /clean /usr/local/apache/htdocs
<Location /clean> SetHandler perl-script PerlHandler My::Clean PerlSetVar Filter On </Location> to PerlHandler My::Clean Apache::Compress
266
Stacked Power http://perl.apache.org/index.html straight HTML
35668 bytes My::Clean 28162 bytes (79%) Apache::Compress 8177 bytes (23%) My::Clean + Apache::Compress 7458 bytes (21%)
268
Fine Manuals Writing Apache Modules with Perl and C
mod_perl Developer's Cookbook mod_perl Pocket Reference mod_perl Guide mod_perl at the ASF
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.