Presentation is loading. Please wait.

Presentation is loading. Please wait.

Geoffrey Young geoff@modperlcookbook.org mod_perl: do more) Geoffrey Young geoff@modperlcookbook.org http://www.modperlcookbook.org/

Similar presentations


Presentation on theme: "Geoffrey Young geoff@modperlcookbook.org mod_perl: do more) Geoffrey Young geoff@modperlcookbook.org http://www.modperlcookbook.org/"— Presentation transcript:

1 Geoffrey Young geoff@modperlcookbook.org
mod_perl: do more) Geoffrey Young

2 Just the facts OSCon theme this year is doing more with less
If you ask Joe Developer what mod_perl is, he quacks "It's basically just faster CGI" That's not exactly right...

3 Request Phases Apache breaks down request processing into separate, logical parts called phases Each request is stepped through the phases in turn until... all processing is complete somebody throws an "error"

4 So What? Most Apache users don't worry about the request cycle too much... ...but they do use modules that plug into it

5 ... for instance mod_rewrite:
client request URI-based init mod_rewrite: RewriteRule /favicon.ico$ /images/favicon.ico URI translation

6 ... for instance mod_auth: AuthUserFile .htpasswd client request
URI-based init URI translation file-based init mod_auth: AuthUserFile .htpasswd resource control

7 ... for instance mod_cgi: SetHandler cgi-script client request
URI-based init content URI translation fixups file-based init MIME setting resource control

8 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

9 Enter mod_perl mod_perl embeds a perl interpreter directly within the Apache runtime opens up the Apache API to Perl code offers an interface to each phase of the request cycle We like Perl

10 Registry is just a handler
Apache::Registry is merely a set of (incredibly clever) Perl subroutines that interact with the request cycle Performance gains are made possible due to what mod_perl really is Let's take a peek inside...

11 Apache::Registry Client side Server side
Server side mod_perl intercepts content generation for Apache/Registry.pm calls Apache::Registry::handler(Apache->request) inserts wizardry returns response to client (a la CGI)

12 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 within Apache the (compiled) package is already in memory when called

13 Do more with less? Most developer's haven't even scratched the surface of what's possible with mod_perl Almost 25% of Apache servers are running mod_perl Why do more with less? Do more with what you already have

14 Do more mod_perl allows you to interact with and directly alter server behavior Gives you the ability to "program within Apache's framework instead of around it" Allows you to intercept basic Apache functions and replace them with your own (sometimes devious) Perl substitutes Lets you do it all in Perl instead of C

15 For Instance... With mod_perl, it's easy to protect our name-based virtual hosts from HTTP/1.0 requests Apache can't handle

16 HTTP/1.0 and Host HTTP/1.0 does not require a Host header
assumes a "one host per IP" configuration this limitation breaks name-based virtual host servers for browsers that follow HTTP/1.0 to the letter most send the Host header, so all is well

17 Let's fix it Intercept every request prior to content-generation and return an error unless... there is a Host header the request is an absolute URI

18 package Cookbook::TrapNoHost;
use Apache::Constants qw(DECLINED BAD_REQUEST); use Apache::URI; use strict; sub handler { my $r = shift; # Valid requests for name based virtual hosting are: # requests with a Host header, or # requests that are absolute URIs. unless ($r->headers_in->get('Host') || $r->parsed_uri->hostname) { $r->custom_response(BAD_REQUEST, "Oops! Did you mean to omit a Host header?\n"); return BAD_REQUEST; } return DECLINED; 1;

19 Setup add TrapNoHost.pm to @INC add to httpd.conf that's it!
ServerRoot/lib/perl/Cookbook/TrapNoHost.pm add to httpd.conf PerlModule Cookbook::TrapNoHost PerlTransHandler Cookbook::TrapNoHost that's it!

20 Apache Request Cycle client request logging URI-based init content
URI translation fixups file-based init MIME setting resource control

21 Intercept the Request client request URI-based init PerlTransHandler
HTTP/ Bad Request Date: Tue, 04 Jun :17:52 GMT Server: Apache/ dev (Unix) mod_perl/1.27_01-dev Perl/v5.8.0 Connection: close Content-Type: text/html; charset=iso Oops! Did you mean to omit a Host header?

22 Intercept the Request client request logging URI-based init
PerlTransHandler

23 Modularize Processing
Parsing out the query string or POST data on each request is a pain For the most part, you know you need it for every request to a given <Location> Take advantage of the request cycle Modularize the parsing code

24 Apache::RequestNotes
Apache::RequestNotes parses cookies and input parameters stores the data in pnotes() for later retrieval

25 Setup Alias /perl-bin /usr/local/apache/perl-bin
<Location /perl-bin/> SetHandler perl-script PerlHandler Apache::Registry Options +ExecCGI PerlInitHandler Apache::RequestNotes </Location>

26 <Location> Processing
client request URI-based init URI translation PerlInitHandler my $input = $r->pnotes('INPUT'); # Apache::Table reference my $uploads = $r->pnotes('UPLOADS'); # Apache::Upload array ref my $cookies = $r->pnotes('COOKIES'); # hash reference

27 User Authentication Some .htaccess file or httpd.conf
AuthUserFile .htpasswd AuthName "my site" AuthType Basic Require valid-user

28 Who Uses Flat Files? flat files are limiting, hard to manage, difficult to integrate, and just plain boring we can do more and replace flat files with our own authentication mechanism

29 package My::Authenticate; use Apache::Constants qw(OK AUTH_REQUIRED);
use strict; sub handler { my $r = shift; # 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; }

30 Configuration change to AuthUserFile .htpasswd AuthName "my site"
AuthType Basic Require valid-user to PerlAuthenHandler My::Authenticate AuthName "cookbook"

31 Authentication HTTP/1.1 401 Authorization Required client request
URI-based init URI translation file-based init PerlAuthenHandler HTTP/ Authorization Required

32 Authentication client request logging URI-based init URI translation
file-based init PerlAuthenHandler

33 The Choice is Yours How you decide to authenticate is now up to you
sub authenticate_user { my ($user, $pass) return $user eq $pass; } Are you seeing the possibilities yet?

34 The Power of CPAN Over 25 Apache:: shrink-wrapped modules on CPAN for authentication SecureID Radius SMB LDAP NTLM

35 Logging Apache's default is to use mod_log_config in common format
LogFormat "%h %l %u %t \"%r\" %>s %b" common CustomLog logs/access_log common Most people tweak this to combined LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

36 Logging to a Database In general, people in marketing don't know what they want when it comes to reports Logging directly to a database makes life easier if you have an application for which you need lots of reports Incurs very little overhead if you are already using a database in your application

37 package Cookbook::SiteLog; use Apache::Constants qw(OK); use DBI;
use strict; sub handler { my $r = shift; my $dbh = DBI->connect($r->dir_config('DBASE'), {RaiseError => 1, AutoCommit => 1, PrintError => 1}) or die $DBI::errstr; my %columns = ( status => $r->status, bytes => $r->bytes_sent, language => $r->headers_in->get('Accept-Language'), ); my $fields = join "$_,", keys %columns; my $values = join ', ', ('?') x values %columns; my $sql = qq( insert into (hit, servedate, $fields) values (hitsequence.nextval, sysdate, $values) my $sth = $dbh->prepare($sql); $sth->execute(values %columns); return OK; } 1;

38 Logging client request PerlLogHandler URI-based init content
URI translation fixups file-based init MIME setting resource control

39 Speedy DBI Apache::DBI rocks Reduces connection overhead
"Works like magic" (action-at-a-distance) PerlModule Apache::DBI Speeds up both legacy CGI and mod_perl applications

40 Use what you have Programming using the request cycle represents an entirely different way of looking at your web applications Apache provides a rich API for interacting with the request mod_perl passes the savings to you

41 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

42 Materials These slides My modules
My modules

43


Download ppt "Geoffrey Young geoff@modperlcookbook.org mod_perl: do more) Geoffrey Young geoff@modperlcookbook.org http://www.modperlcookbook.org/"

Similar presentations


Ads by Google