Presentation is loading. Please wait.

Presentation is loading. Please wait.

(Brief) Introduction to mod_perl

Similar presentations


Presentation on theme: "(Brief) Introduction to mod_perl"— Presentation transcript:

1 (Brief) Introduction to mod_perl
Geoffrey Young

2

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)

103

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

150

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

204

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%)

267

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

269


Download ppt "(Brief) Introduction to mod_perl"

Similar presentations


Ads by Google