home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Writing Apache Modules with Perl and C
By:   Lincoln Stein and Doug MacEachern
Published:   O'Reilly & Associates, Inc.  - March 1999

Copyright © 1999 by O'Reilly & Associates, Inc.


 


   Show Contents   Previous Page   Next Page

Chapter 9 - Perl API Reference Guide / The Apache Request Object
Sending Data to the Client

The methods in this section are invoked by content handlers to send header and document body data to the waiting browser. Noncontent handlers should not call these methods.

print()

The Apache C API provides several functions for sending formatted data to the client. However, Perl is more flexible in its string handling functions, so only one method, print(), is needed.

The print() method is similar to Perl's built-in print() function, except that all the data you print eventually winds up being displayed on the user's browser. Like the built-in print(), this method will accept a variable number of strings to print out. However, the Apache print() method does not accept a filehandle argument for obvious reasons.

Like the read() method, print() sets a timeout so that if the client connection is broken, the handler won't hang around indefinitely trying to send data. If a timeout does occur, the script will be aborted.

The method also checks the Perl autoflush global $|. If the variable is nonzero, print() will flush the buffer after every command, rather than after every line. This is consistent with the way the built-in print() works.

$r->print("hello" , " ", "world!");

An interesting feature of the Apache Perl API is that the STDOUT filehandle is tied to Apache so that if you use the built-in print() to print to standard output, the data will be redirected to the request object's print() method. This allows CGI scripts to run unmodified under Apache::Registry, and also allows one content handler's output to be transparently chained to another handler's input. The section "The Apache TIEHANDLE Interface" later in this chapter goes into more detail on tying filehandles to the Perl API, and Chapter 4 has more to say about chained handlers.

print "hello world!";  # automatically invokes Apache::print()

There is also an optimization built into print(). If any of the arguments to the method are scalar references to strings, they are automatically dereferenced for you. This avoids needless copying of large strings when passing them to subroutines.

$a_large_string = join '', <GETTYSBURG_ADDRESS>;
$r->print(\$a_large_string);

printf()

The printf() method works just like the built-in function of the same name, except that the data is sent to the client. Calling the built-in printf() on STDOUT will indirectly invoke this method because STDOUT is tied.

$r->printf("Hello %s", $r->connection->user);

rflush()

For efficiency's sake, Apache usually buffers the data printed by the handler and sends it to the client only when its internal buffers fill (or the handler is done). The rflush() method causes Apache to flush and send its buffered outgoing data immediately. You may wish to do this if you have a long-running content handler and you wish the client to begin to see the data sooner.

Don't call rflush() if you don't need to, because it causes a performance hit.3 This method is also called automatically after each print() if the Perl global variable $| is nonzero.

$r->rflush;

send_cgi_header()

As we mentioned in the section on cgi_header_out(), the mod_cgi module scans for and takes special action on certain header fields emitted by CGI scripts. Developers who wish to develop a CGI emulation layer can take advantage of send_cgi_header(). It accepts a single string argument formatted like a CGI header, parses it into fields, and passes the parsed fields to cgi_header_out(). cgi_header_out() then calls send_http_header() to send the completed header to the browser.

Don't forget to put a blank line at the end of the headers, just as a CGI script would:

$r->send_cgi_header(<<EOF);
Status: 200 Just Fine
Content-type: text/html
Set-cookie: open=sesame
EOF

You're welcome to use this method even if you aren't emulating the CGI environment, since it provides a convenient one-shot way to set and send the entire HTTP header; however, there is a performance hit associated with parsing the header string.

As an aside, this method is used to implement the behavior of the PerlSendHeader directive. When this directive is set to On, mod_perl scans the first lines of text printed by the content handler until it finds a blank line. Everything above the blank line is then sent to send_cgi_header().

send_fd()

Given an open filehandle, filehandle glob, or glob reference as argument, this method sends the contents of the file to the client. Internally, the Perl interface extracts the file descriptor from the filehandle and uses that directly, which is generally faster than calling the higher-level Perl methods. The confusing naming of this method (it takes a filehandle, not a file descriptor) is for consistency with the naming of the corresponding C API function call.

This method is generally used by content handlers that wish to send the browser the unmodified contents of a file.

my $fh = Apache::gensym();  # generate a new filehandle name
open($fh, $r->filename) || return NOT_FOUND;
$r->send_fd($fh);
close($fh);

send_http_header()

This method formats the outgoing response data into a proper HTTP response and sends it to the client. The header is constructed from values previously set by calls to content_type(), content_encoding(), content_language(), status_line(), and headers_out(). Naturally, this method should be called before any other methods for sending data to the client.

Because setting the document's MIME type is such a common operation, the Perl version of this API call allows you to save a few keystrokes by specifying the content type as an optional argument to send_http_header(). This is exactly equivalent to calling content_ type() followed by send_http_header().

$r->send_http_header;
$r->send_http_header('text/plain');

A content type passed to send_http_header() will override any previous calls to content_type().

   Show Contents   Previous Page   Next Page
Copyright © 1999 by O'Reilly & Associates, Inc.