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 10 - C API Reference Guide, Part I / Processing Requests
Sending Files to the Client

As we learned in Chapter 4, sending a plain file over HTTP requires a few more considerations than one might think. Here we list the C API functions upon which the Apache::File module is built:

int ap_set_content_length (request_rec *r, long length)

This method sets the outgoing Content-length header based on the length argument. By using this method, you avoid the hassle of converting the long value to a string, along with saving a few keystrokes. The return value is always zero and can be safely ignored.

(void)ap_set_content_length(r, r->finfo.st_size);

void ap_set_etag (request_rec *r)

This method is used to set the outgoing ETag header, described in Chapter 3 in the section "The HTTP Protocol." Use this if your content handler is serving static files. Sending the entity tag allows HTTP/1.1-compliant clients to intelligently cache documents locally and only update them when they change on the server.

ap_set_etag(r);

time_t ap_update_mtime (request_rec *r, time_t dependency_mtime)

(Declared in the header file http_request.h.) Browsers will cache static documents locally and update them only when the server indicates they have changed. They do this by comparing the current document's HTTP Last-modified field to the value of this field when the document was last cached. Apache derives the Last-modified field from the request record's mtime field, which by default is set to the filesystem modification time of the requested file. This default is appropriate for a document that is a simple static file but not a document that is created dynamically, for example, a server-side include file that depends on one or more configuration files.

In such cases, you can use this function to set the mtime field to reflect the appropriate modification time, taking into account any of the document's dependencies on configuration files and other resources. Its two arguments are the request record and dependency_mtime. The mtime field will be updated if and only if the current mtime is older than the dependency_mtime. Therefore, if the final document depends on several configuration files, it is safe to call ap_update_mtime() once with the modification times of each configuration file. At the end of this series of calls the mtime field will be set to the most recent date, allowing the Last-modified field to accurately reflect the modification time of the requested document. Of course, the true modification time of the requested file as reported by the filesystem is unaffected by this maneuver.

This function's return value is the value of the updated mtime. If your handler is serving static files without modifying them en route, you will not need to call this function because Apache will already have set mtime appropriately. Before sending the headers, you should also be sure to call ap_set_last_modified() (discussed next) in order to use the value of mtime to create the Last-modified field in the outgoing headers table.

In the following example, we update the file's modification time from a dependency on a configuration file named templates.conf:

struct stat conf_info;
char* conf_file = server_root_relative(r->pool, "conf/templates.conf");
if (stat(conf_file, &conf_info) == 0) {
  ap_update_mtime(r, conf_info.st_mtime);
}
ap_set_last_modified(r);

void ap_set_last_modified (request_rec *r)

This method is used to set the Last-modified header using the value of r->mtime. If mtime is in the future, the header field will not be modified. This function should be called whenever you are serving static files or server-side include files and want the client to be able to cache the document contents locally. You might also want to use this function, in conjunction with ap_update_mtime(), if you are creating documents from database records and have some sort of timestamp in the records that enables you to determine when the data was last changed.

ap_set_last_modified(r);

See also ap_update_mtime().

int ap_meets_conditions (request_rec *r)

As described in Chapter 9 in "The Apache::File Class," the ap_meets_conditions() function is used to implement "conditional GET" semantics.

if((rc = ap_meets_conditions(r) != OK) {
   return rc;
}

int ap_discard_request_body (request_rec *r)

Also described in Chapter 9, this utility function is used to throw away the request body.

if((rc = ap_discard_request_body(r) != OK) {
   return rc;
}

long ap_send_ fd (FILE *f, request_rec *r)

The ap_send_ fd() function sends the contents of the file pointed to by FILE* to the client and returns the number of bytes transmitted. This is a useful way to return a file to the client if you don't need to modify it on the fly. In this example, we open the file requested by the URI using the ap_pfopen() call. If successful, we send its contents, then close the file.

FILE *f = ap_pfopen(r->pool, r->filename, "r");
if (f == NULL) {
   return NOT_FOUND;
}
ap_send_fd(f, r);
ap_pfclose(r->pool, f);

long ap_send_ fd_length (FILE *f, request_rec *r, long length)

This function works like ap_send_fd(), but only length bytes of data are sent. If you pass a negative value for length, the entire file will be sent, which, in fact, is what ap_send_fd() does internally. The function result is the number of bytes sent, or -1 if an error occurred before any bytes could be sent.

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