The Apache API

The Apache API

Among all the other things it was meant to be, Apache is also a cross-platform server. As a result, a module developer can't rely on the availablity of POSIX libraries. Apache provides a large API to perform functions like string handling, resource management, and process management, and we'll need to know about these in order to build modules. All these functions are distinguished by the prefix ap_ (which is a good practice in the C world.) But before I introduce some of the common functions, I'll need to describe two more concepts: the request structure and resource pools.

The Request Structure

Most of the handler functions you'll write for custom-built modules are passed a single argument, a pointer to a request structure, of type struct request_rec *. This structure contains everything Apache knows about the current request. Many of the Apache API functions operate on this structure and take a pointer to it as their first argument. Some of the important fields are listed next , in a liberally edited version of the request_rec structure. The full description is found in the header file httpd.h.

 struct request_rec { 
 /* General information */ 
 
 pool *pool; /* The request's resource pool */ 
 conn_rec *connection; /* Information about the connection and client */ 
 server_rec *server; /* Information about this server */ 
 const char *hostname; /* Hostname from URI or Host: header */ 
 void *per_dir_config; /* Options set in config files, etc. */ 
 void *request_config; /* Notes on *this* request */ 
 
 /* Request information. Usually not changed. */ 
 
 char *unparsed_uri; /* The unparsed URI */ 
 char *uri; /* The path part of the requested URI */ 
 char *filename; /* The filename to which this URI translates */ 
 char *path_info; /* Additional path information */ 
 char *args; /* Query string, if present */ 
 int header_only; /* 0 = GET, 1 = HEAD request */ 
 char *protocol; /* Protocol, as given to us, or HTTP/0.9 */ 
 char *method; /* GET, HEAD, POST, etc. */ 
 int method_number; /* M_GET, M_POST, etc. */ 
 
 /* Response information. Usually modified by a handler function. */ 
 
 char *content_type; /* This should be set by the handler function */ 
 char *content_encoding; 
 int bytes_sent; /* Used for logging */ 
 int no_cache; /* Can be set to suppress client caching 
 */ 
 }; 

Resource Pools

An Apache resource pool is a structure that, at its simplest, manages memory and files so that you don't have to. Resource pools can ease some of the difficulties with string handling in C. For example, if you need to concatenate two strings, traditionally you would allocate a buffer of the appropriate size with malloc and use strncat . However, you need to keep track of the pointer and free the memory when it's no longer needed. If the string is relevant only within a certain function, you can simplify things by using a character array on the stack. But if the string needs to be passed around from function to function, it's hard to know where to perform the deallocation.

Using a resource pool, on the other hand, is trivial:

 char *new_string = ap_pstrcat(r->pool, "http://www.myserver.com", path, "/favicon.ico"); 

new_string is created by concatenating all the arguments provided to ap_pstrcat. It's "owned" by the resource pool, and you don't have to be concerned with deallocating it at some point in the future. It will be freed when the pool is destroyed by Apache during its normal course of operation. The Apache API provides many other resource pool functions; here is a simple way to obtain the list:

 grep -l API_EXPORT /usr/include/apache-1.3/*.h  grep "struct pool" 

Apache creates several types of resource pools with different scope. There is one global resource pool that exists for the lifetime of the server process. There are resource pools for the individual server threads (or processes.) But the resource pool you'll make use of as a module developer belongs to an individual request. It's created when the request is received, and destroyed when the request is finished. As we saw earlier, the request structure contains a pointer to this pool.

Commonly Used Functions

There are a number of functions from the Apache API that you'll use over and over, so I'll introduce a few of the most common ones here. It's by no means an exhaustive list; you can obtain a full enumeration of the Apache API by searching for the word "API_EXPORT" in the header files. However, it's difficult to determine the exact behavior of a function from looking at just its signature, so it's often useful to use the Apache source distribution as a usage guide. Simply search for the function you're interested in and see how it's used in the standard modules.

Without further ado, here's my "top ten or so" list of most important functions.

 void ap_send_http_header(request_rec *r) 
 
 void ap_send_fd(FILE *file, request_rec *r) 

The first function forces the HTTP headers to be sent. You should always call this function before you start writing to the body of the HTTP response. The second one sends the content of a file opened with fopen directly to the HTTP response. These two functions are really all that's necessary to serve simple files.

 void ap_rputc(char c, request_rec *r) 
 
 void ap_rputs(char *s, request_rec *r) 
 
 void ap_rprintf(request_rec *r, char *fmt, ...) 
 
 int ap_rwrite(const void *buf, int nbyte, request_rec *r) 
 
 void ap_rvputs(request_rec *r, char *s, ...) 
 
 int ap_rflush(request_rec *r) 

These functions all send output to the body of an HTTP response. The behavior of the first four are analogous to putc, puts, printf, and write, respectively. The fifth function is a convenient time saver. It takes a variable number of arguments, all strings, and concatenates them together to the response. This allows you to write things like this:

  char *link, *text;  
  ap_rvputs(req, "<a href=\"", link, "\">", text, "</a>");  

which outputs the HTML for a hyperlink, given two variable strings. Finally, the last function allows you to flush the output buffer.

  void ap_log_rerror(int line, int level, const request_rec *s, const char *fmt, ...)  

This function writes an entry to the error log. The constants for the level argument are defined in http_log.h, and the arguments following request_rec *s are in the same style as printf.

  void *ap_palloc(struct pool *, int nbytes)  
   
  void *ap_pcalloc(struct pool *, int nbytes)  
   
  char *ap_pstrdup(struct pool *, const char *s)  
   
  char *ap_pstrcat(struct pool *, ...)  
   
  char *ap_psprintf(struct pool *, const char *fmt, ...)  

These functions are all memory and string-handling functions. All needed space is allocated from the specified resource pool, and you don't have to worry about freeing this space later on; it will be released when the pool is destroyed. Under normal circumstances, you'll use the pool provided by the request structure, so any memory you use will be freed as soon as the request is finished.

The first two functions are worry-free versions of malloc and calloc , if you need to use variable- sized buffers in your code. Of course, you're still free to use local buffers allocated on the stack. ap_pstrcat and ap_psprintf mirror ap_rvputs and ap_rprintf, respectively, but they return new strings allocated in the pool instead of writing to the HTTP response body.

 



Multitool Linux. Practical Uses for Open Source Software
Multitool Linux: Practical Uses for Open Source Software
ISBN: 0201734206
EAN: 2147483647
Year: 2002
Pages: 257

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net