To notify clients that the server is configured with
KeepAlive Off, clients must be told that the
connection will be closed after the content has been delivered:
Connection: close
There can be other headers as well, such as caching control headers
and others specified by the HTTP protocol. You can code the response
header with a single print(
) statement:
print qq{HTTP/1.1 200 OK
Date: Tue, 10 Apr 2001 03:01:36 GMT
Server: Apache/1.3.19 (Unix) mod_perl/1.25
Connection: close
Content-Type: text/plain
};
Don't forget to include two
newlines at the end of the HTTP header. With
the help of Apache::Util::ht_time( ), you can get
the right timestamp string for the Date: field.
If you want to send non-default headers, use the header_out(
) method. For example:
When the headers setting is completed, the send_http_header(
) method will flush the headers and add a
newline to designate the start of the content.
$r->send_http_header;
Some headers have special
aliases. For example:
$r->content_type('text/plain');
is the same as:
$r->header_out("Content-Type" => "text/plain");
but additionally sets some internal flags used by Apache. Whenever
special-purpose methods are available, you should use those instead
of setting the header directly.
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:
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:
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_printedserves 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.
6.10. Handling Server Timeout Cases and Working with $SIG{ALRM}
6.12. Method Handlers: The Browse and See, Browse and View Example