spacer

Webref WebRef   Sitemap · Experts · Tools · Services · Newsletters · About i.com

home / programming / perl / mod_perl / chap6 / 4 To page 1To page 2To page 3current pageTo page 5To page 6
[previous] [next]

Practical mod_perl: Chapter 6: Coding with mod_perl in Mind

Market Data Analyst (IL)
Next Step Systems
US-IL-Chicago

Justtechjobs.com Post A Job | Post A Resume
Developer News
OpenOffice 3.2 Lands Amid Critical Changes
Red Hat, IBM Firmly in KVM Virtualization Camp
Red Hat Talks Up Open Source Cloud Plans


A typical handler looks like this:

use Apache::Constants qw(OK);
$r->content_type('text/plain');
$r->send_http_header;
return OK if $r->header_only;

To be compliant with the HTTP protocol, if the client issues an HTTP HEAD request rather than the usual GET, we should send only the HTTP header, the document body. When Apache receives a HEAD request, header_only( ) returns true. Therefore, in our example the handler returns immediately after sending the headers.

In some cases, you can skip the explicit content-type setting if Apache figures out the right MIME type based on the request. For example, if the request is for an HTML file, the default text/html will be used as the content type of the response. Apache looks up the MIME type in the mime.types file. You can always override the default content type.

The situation is a little bit different with Apache::Registry and similar handlers. Consider a basic CGI script:

print "Content-type: text/plain\n\n";
print "Hello world";

By default, this won't work, because it looks like normal text, and no HTTP headers are sent. You may wish to change this by adding:

PerlSendHeader On

in the Apache::Registry <Location> section of your configuration. Now the response line and common headers will be sent in the same way they are by mod_cgi. Just as with mod_cgi, even if you set PerlSendHeader On, the script still needs to send the MIME type and a terminating double newline:

print "Content-type: text/html\n\n";

The PerlSendHeader On directive tells mod_perl to intercept anything that looks like a header line (such as Content-Type: text/plain) and automatically turn it into a correctly formatted HTTP header, much like CGI scripts running under mod_cgi. This feature allows you to keep your CGI scripts unmodified.

You can use $ENV{PERL_SEND_HEADER} to find out whether PerlSendHeader is On or Off.

if ($ENV{PERL_SEND_HEADER}) {
    print "Content-type: text/html\n\n";
}
else {
    my $r = Apache->request;
    $r->content_type('text/html');
    $r->send_http_header;
}

Note that you can always use the code in the else part of the above example, whether the PerlSendHeader directive is On or Off.

If you use CGI.pm's header( ) function to generate HTTP headers, you do not need to activate this directive because CGI.pm detects mod_perl and calls send_http_header( ) for you.

There is no free lunch--you get the mod_cgi behavior at the expense of the small but finite overhead of parsing the text that is sent. Note that mod_perl makes the assumption that individual headers are not split across print( ) statements.

The Apache::print( ) routine must gather up the headers that your script outputs in order to pass them to $r->send_http_header. This happens in src/modules/perl/Apache.xs (print( )) and Apache/Apache.pm (send_cgi_header( )). There is a shortcut in there--namely, the assumption that each print( ) statement contains one or more complete headers. If, for example, you generate a Set-Cookie header using multiple print( ) statements, like this:

print "Content-type: text/plain\n";
print "Set-Cookie: iscookietext\; ";
print "expires=Wednesday, 09-Nov-1999 00:00:00 GMT\; ";
print "path=\/\; ";
print "domain=\.mmyserver.com\; ";
print "\n\n";
print "Hello";

the generated Set-Cookie header is split over a number of print( ) statements and gets lost. The above example won't work! Try this instead:

my $cookie = "Set-Cookie: iscookietext\; ";
$cookie .= "expires=Wednesday, 09-Nov-1999 00:00:00 GMT\; ";
$cookie .= "path=\/\; ";
$cookie .= "domain=\.mmyserver.com\; ";
print "Content-type: text/plain\n",
print "$cookie\n\n";
print "Hello";

Using special-purpose cookie generator modules (for example, Apache::Cookie or CGI::Cookie) is an even cleaner solution.

Sometimes when you call a script you see an ugly "Content-Type: text/html" displayed at the top of the page, and often the HTML content isn't rendered correctly by the browser. As you have seen above, this generally happens when your code sends the headers twice.

If you have a complicated application in which the header might be sent from many different places depending on the code logic, you might want to write a special subroutine that sends a header and keeps track of whether the header has already been sent. You can use a global variable to flag that the header has already been sent, as shown in Example 6-38.

Example 6-38: send_header.pl

use strict;
use vars qw($header_printed);
$header_printed = 0;
 
print_header("text/plain");
print "It worked!\n";
print_header("text/plain");
 
sub print_header {
    return if $header_printed;
    
    my $type = shift || "text/html";
    $header_printed = 1;
    my $r = Apache->request;
    $r->content_type($type);
    $r->send_http_header;
}
1;

$header_printed serves as a Boolean variable, specifying whether the header was sent or not. It gets initialized to false (0) at the beginning of each code invocation. Note that the second invocation of print_header( ) within the same request will immediately return, since $header_printed will become true after print_header( ) is executed for the first time in the same request.

You can continue to improve this subroutine even further to handle additional headers, such as cookies.

home / programming / perl / mod_perl / chap6 / 4 To page 1To page 2To page 3current pageTo page 5To page 6
[previous] [next]


The Network for Technology Professionals

Search:

About Internet.com

Legal Notices, Licensing, Permissions, Privacy Policy.
Advertise | Newsletters | E-mail Offers

webref The latest from WebReference.com Browse >
Search Engine Optimization: Selecting and Embedding Keywords · Are Google's Language Translation Web Services Ready for Prime Time? · Installing and Using Meeplace, the Business Review CMS
Sitemap · Experts · Tools · Services · Email a Colleague · Contact FREE Newsletters 
 The latest from internet.com
IBM DB2 10 for z/OS: Justifying the Upgrade · Living La Vida Colo: Choosing the Right Colocation Facility · FTC Concerns over Social Media Privacy Linger

Created: March 27, 2003
Revised: July 23, 2003

URL: http://webreference.com/programming/perl/mod_perl/chap6/4