ࡱ > 7 } bjbjUU 4 7| 7| Fy g l 2 R R R 8 R S 2 h ^U Z [ [ [ \ ` d Cb Z \ \ \ \ \ \ ? \ b [ [ " b b \ [ [ q b \ [ [ Z b Z ͚ [ RU %tI2 N R Sz z 6 | 0 . א 2 2
Modules and the Apache Web Server
Jason Armstrong
jason@datrix.co.za
Table of Contents
TOC \o "1-2" \h \z
HYPERLINK \l "_Toc497733021" The Apache Software Foundation PAGEREF _Toc497733021 \h 3
HYPERLINK \l "_Toc497733022" What is Apache PAGEREF _Toc497733022 \h 4
HYPERLINK \l "_Toc497733023" Apache Usage PAGEREF _Toc497733023 \h 4
HYPERLINK \l "_Toc497733024" Top Servers PAGEREF _Toc497733024 \h 4
HYPERLINK \l "_Toc497733025" Apache Modules: An Overview PAGEREF _Toc497733025 \h 5
HYPERLINK \l "_Toc497733026" Simple Module PAGEREF _Toc497733026 \h 6
HYPERLINK \l "_Toc497733027" Purpose of our module PAGEREF _Toc497733027 \h 6
HYPERLINK \l "_Toc497733028" Declaring a handler PAGEREF _Toc497733028 \h 6
HYPERLINK \l "_Toc497733029" Simple Handler Function PAGEREF _Toc497733029 \h 7
HYPERLINK \l "_Toc497733030" Building our module into Apache PAGEREF _Toc497733030 \h 8
HYPERLINK \l "_Toc497733031" Configuring Apache to use our module PAGEREF _Toc497733031 \h 8
HYPERLINK \l "_Toc497733032" Module Structure PAGEREF _Toc497733032 \h 9
HYPERLINK \l "_Toc497733033" Purpose of module PAGEREF _Toc497733033 \h 9
HYPERLINK \l "_Toc497733034" Module declaration PAGEREF _Toc497733034 \h 9
HYPERLINK \l "_Toc497733035" Apache structures and their usage PAGEREF _Toc497733035 \h 10
HYPERLINK \l "_Toc497733036" The command_rec structure PAGEREF _Toc497733036 \h 10
HYPERLINK \l "_Toc497733037" The handler_rec structure PAGEREF _Toc497733037 \h 11
HYPERLINK \l "_Toc497733038" The server_rec structure PAGEREF _Toc497733038 \h 12
HYPERLINK \l "_Toc497733039" The conn_rec structure PAGEREF _Toc497733039 \h 12
HYPERLINK \l "_Toc497733040" The request_rec structure PAGEREF _Toc497733040 \h 12
HYPERLINK \l "_Toc497733041" Initialising and reading configuration PAGEREF _Toc497733041 \h 13
HYPERLINK \l "_Toc497733042" Linux 2000 Handler PAGEREF _Toc497733042 \h 14
HYPERLINK \l "_Toc497733043" Linux 2000 Configuration PAGEREF _Toc497733043 \h 15
HYPERLINK \l "_Toc497733044" Apache 2.0 PAGEREF _Toc497733044 \h 16
HYPERLINK \l "_Toc497733045" More information PAGEREF _Toc497733045 \h 17
HYPERLINK \l "_Toc497733046" Acknowledgements PAGEREF _Toc497733046 \h 17
HYPERLINK \l "_Toc497733047" References PAGEREF _Toc497733047 \h 17
HYPERLINK \l "_Toc497733048" Addendum One PAGEREF _Toc497733048 \h 18
HYPERLINK \l "_Toc497733049" mod_simple.c source code PAGEREF _Toc497733049 \h 18
HYPERLINK \l "_Toc497733050" Addendum Two PAGEREF _Toc497733050 \h 19
HYPERLINK \l "_Toc497733051" mod_linux2000.c source code PAGEREF _Toc497733051 \h 19
HYPERLINK \l "_Toc497733052" Addendum Three PAGEREF _Toc497733052 \h 21
HYPERLINK \l "_Toc497733053" server_rec structure PAGEREF _Toc497733053 \h 21
HYPERLINK \l "_Toc497733054" Addendum Four PAGEREF _Toc497733054 \h 22
HYPERLINK \l "_Toc497733055" conn_rec structure PAGEREF _Toc497733055 \h 22
HYPERLINK \l "_Toc497733056" Addendum Five PAGEREF _Toc497733056 \h 23
HYPERLINK \l "_Toc497733057" request_rec structure PAGEREF _Toc497733057 \h 23
HYPERLINK \l "_Toc497733058" Addendum Six PAGEREF _Toc497733058 \h 25
HYPERLINK \l "_Toc497733059" POST and GET data PAGEREF _Toc497733059 \h 25
The Apache Software Foundation
The Apache httpd web server is one of the projects being run under the auspices of the Apache Software Foundation [1].
The Apache Software Foundation (ASF) is a not-for-profit corporation, incorporated in Delaware, USA, in June of 1999. The ASF is a natural outgrowth of The Apache Group, a group of individuals that was initially formed in 1995 to develop the Apache HTTP Server.
The Foundation was formed primarily to:
provide a foundation for open, collaborative software development projects by supplying hardware, communication, and business infrastructure;
create an independent legal entity to which companies and individuals can donate resources and be assured that those resources will be used for the public benefit;
provide a means for individual volunteers to be sheltered from legal suits directed at the Foundation's projects; and,
protect the 'Apache' brand, as applied to its software products, from being abused by other organizations.
The ASF co-ordinates other open-source projects, among them:
The Apache XML Project [2]
Jakarta (Tomcat and Josper, two server-side Java projects) [3]
Java-Apache (other server-side Java projects: JServ, JSSI, Cocoon) [4]
mod_perl [5]
PHP (a server-side, cross-platform, HTML embedded scripting language) [6]
What is Apache
The Apache httpd server:
is a powerful, flexible, HTTP/1.1 compliant web server
implements the latest protocols, including HTTP/1.1 (RFC2616)
is highly configurable and extensible with third-party modules
can be customised by writing 'modules' using the Apache module API
provides full source code and comes with an unrestrictive license
runs on Windows NT/9x, Netware 5.x, OS/2, and most versions of Unix,
as well as several other operating systems
is actively being developed
encourages user feedback through new ideas, bug reports and patches
Apache Usage
The following statistics are taken from the Netcraft Survey [7]
The Netcraft Web Server Survey is a survey of Web Server software usage on Internet connected computers.
The October 2000 survey received responses from 22,282,727 sites.
Top Servers
ServerSept 2000%Oct 2000%ChangeApache1270519460.021329549959.67-0.35Microsoft-IIS413855119.55449160920.160.61Netscape-Enterprise14726896.9615009886.74-0.22WebLogic5665092.686803323.050.37Zeus6069872.876162002.77-0.10Rapidsite3322461.573393791.52-0.05thttpd1903710.902251751.010.11AOLserver2014710.951519480.68-0.27WebSitePro1036170.491051120.47-0.02tigershark815280.391028500.460.07
Apache Modules: An Overview
Modules make it possible for developers to extend the functionality of Apache. A module is a custom written piece of code which can be plugged into the main Apache server, and which can be called at various stages of an http request.
Note: For these examples, I am using the Apache 1.3 code base and API routines. The functions and code detailed in this paper utilize the C programming language.
An http request is handled in a series of steps. These are:
URI -> Filename translation
Auth ID check
Auth access check
Other access checks
Determine MIME type of requested object
Fixups
Send a response
Log the request
These phases are handled by looking at a succession of modules and seeing if it has a handler for the phase. If it does, the handler is invoked.
Handlers are functions that take one argument, a request_rec structure, which we will look at later. They return an integer, as detailed below.
Handlers can do one of three things:
Handle the request, and return OK
Decline the request, returning DECLINED
Signal an error by returning an HTTP error code
What we will do is to declare our interest in a particular phase, and tell Apache that we want to handle that request.
A number of modules exist for Apache and are incorporated into the Apache distribution. Among these are:
PHP module (mod_php)
Rewrite module (mod_rewrite)
SSL module (mod_ssl)
DAV: Distributed Authoring and Versioning (mod_dav)
Perl (mod_perl)
MySQL Auth (mod_auth_mysql)
Simple Module
Purpose of our module
We want our module to handle all requests to the URL http://server.name/simple. The module will respond with the time. To add some interest, we will also set the page to refresh every five seconds, thus continually updating the time.
Declaring a handler
We declare our handler in two steps. First, in the module structure, we have a number of hooks. We declare our interest in the handler part of the structure:
module simple_module = {
STANDARD_MODULE_STUFF,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
simple_handler,
NULL
};
Our simple_handler is an array of handler_rec structures, in which we declare the content type of our handler, and a function to deal with it. Ours looks like this:
static const handler_rec simple_handler[] = {
{ simple-handler, handler_simple },
{ NULL }
};
We end with NULL to let Apache know that we dont have any more handlers.
What we have done is to say that when a request is meant to be handled by the
simple-handler content type, then our function handler_simple() must be called.
All we need to do know is write this function, and tell Apache when to use it.
Simple Handler Function
All handler functions take one argument, a pointer to a request_rec structure, which contains a wealth of detail about the request. We will talk about the contents of this structure later.
The first thing we do in our function is to set the content-type field:
r->content_type = text/html;
We then send the http header to the client.
ap_send_http_header(r);
This will look something like:
HTTP/1.1 200 OK
Date: Tue, 31 Oct 2000 13:06:40 GMT
Server: Apache/1.3.14 (Unix)
Connection: close
Content-Type: text/html
We then output HTML to the client, using two of the module API functions, ap_rputs() and ap_rprintf(). The first outputs a string and the second is a string formatting function:
ap_rputs("
\n", r);
ap_rputs("Simple:Time\n", r);
ap_rputs("\n", r);
ap_rprintf(r, "%s
\n", ctime(&now));
ap_rputs("\n", r);
The client will receive:
Simple:Time
Wed Nov 1 11:03:39 2000
See Addendum One for the full source code.
Building our module into Apache
Apache provides two ways to link our module into the server. We can compile the module in statically, or we can compile the module as a DSO (Dynamic Shared Object). I am going to look at the statically compiled option here.
To configure Apache to compile this new module, copy the mod_simple.c source file into the src/modules/extra directory underneath the Apache source distribution. Change to the top level directory, and run the configure script with the following options:
$ ./configure --activate-module=src/modules/extra/mod_simple.c
Then run:
$ make
$ make install
Configuring Apache to use our module
We now need to edit the httpd.conf configuration file to tell Apache when to run our handler.
Add the following lines to the configuration file:
SetHandler simple-handler
This tells Apache that all request for the location /simple should be handled by our module simple-handler.
Restart the server:
$ apachectl restart
Our module will now handle all requests to http://server.name/simple.
Module Structure
Lets look at a more detailed example of the module structure.
Purpose of module
The purpose of this more complex example is to add a configurable text section to the top and bottom of each page. We want to be able to specify this text in Apaches own configuration file, httpd.conf.
Module declaration
module linux2000_module = {
STANDARD_MODULE_STUFF,
NULL, /* initializer */
linux2000_create_dir_config, /* dir config creator */
NULL, /* dir merger */
NULL, /* server config */
NULL, /* merge server config */
linux2000_cmds, /* command table */
linux2000_handler, /* handlers */
NULL
};
Here, weve defined three hooks, one for per directory configuration, one that defines various configuration commands and one that is a table of handlers for the module.
Two of these hooks that weve declared an interest in are the command table and the handler table. Lets look at those two structures, and some of the other important Apache structures, in a little more detail.
Apache structures and their usage
The command_rec structure
This is used to configure various options for this module via the configuration file httpd.conf. We define the name of the directive in the configuration file, which function to use when the directive is encountered, where in the configuration file to read the data from, and what sort of structure the command is in (ie does it have one or two arguments, is it a flag etc). This structure is defined in http_config.h as follows:
typedef struct command_struct {
const char *name; /* Name of this command */
const char *(*func) (); /* Function invoked */
void *cmd_data; /* Extra data, for functions which
* implement multiple commands... */
int req_override; /* What overrides need to be allowed to
* enable this command. */
enum cmd_how args_how; /* What the command expects as arguments */
const char *errmsg; /* 'usage' message, in case of syntax errors */
} command_rec;
Our linux2000_cmds table follows this format:
command_rec linux2000_cmds[] = {
{ "linux2000Header", linux2000_header, NULL, ACCESS_CONF, TAKE1,
"Add a header text to each page" },
{ "linux2000Footer", linux2000_footer, NULL, ACCESS_CONF, TAKE1,
"Add a footer text to each page" },
{ NULL }
};
The two functions pointed to here take the linux2000Header and linux2000Footer parameters from the configuration file, and copy it into our own module specific data structure.
The final directive in the command table must be NULL, letting Apache know that this module has no more directives.
The handler_rec structure
typedef struct {
const char *content_type; /* MUST be all lower case */
int (*handler) (request_rec *);
} handler_rec;
The function pointed to takes one argument, a request_rec structure. In our example, the handler is:
handler_rec linux2000_handler[] = {
{ "linux2000-handler", handler_linux2000 },
{ NULL }
};
and the handler_linux2000 function handles the request. The handler also returns an int, which must be OK, DECLINED or an HTTP error code. If OK is returned, then the handler has taken care of serving the request. If DECLINED is returned, then the handler has decided it is not going to server this request. If an error code is returned, this indicates that an error page must be returned to the client.
Now, a brief look at three other important structures, which give us information about the request being made:
The server_rec structure
Apache understands multiple virtual hosts in the same server, and creates a server_rec for each virtual host on startup. The request_rec contains a pointer to the correct server_rec for each request. This structure contains information about the current server, for example: the name, port, log files etc.
Please see Addendum Three for the full server_rec structure.
The conn_rec structure
This structure stores information about the current connection to Apache. Here you find details of the remote_ip and the remote_host (DNS name of the client, if it is known), as well as details of the socket and keepalives.
A useful field here is the user variable. If an authentication check was made, the value of this variable can be accessed via r->connection->user. So you could, for example, decline to handle a request if the user hasnt been authenticated:
if (!r->connection->user) {
return DECLINED;
}
Please see Addendum Four for the full conn_rec structure.
The request_rec structure
This structure stores information about the current request. It contains pointers to the conn_rec and server_rec for this request, so modules can get all possible information that they need using the request_rec. It also contains details about the type of request being made (GET, POST or HEAD), the protocol (HTTP/1.0, HTTP/1.1 etc), languages, the content type, tables of the headers to be sent out, the URI, whether to cache the request or not, query arguments being sent, information about the file being requested and the result of any authentication directives such as .htaccess files.
Please see Addendum Five for the full request_rec structure.
Initialising and reading configuration
Let's now look at how our linux2000 handler deals with the request. We have a module specific structure, in which we store our configuration data:
typedef struct hf_rec {
char *header;
char *footer;
} hf_rec;
This structure gets initialized when we create the per directory configuration, which weve registered as linux2000_create_dir_config().
The values in the httpd.conf file get read, as defined in the command table by the functions linux2000_header() and linux2000_footer(). These values get stored in our modules data structure.
Linux 2000 Handler
We read in the modules per directory configuration via the ap_get_module_config() function call:
hf_rec *conf = (hf_rec *) ap_get_module_config(r->per_dir_config,
&linux2000_module);
Then we set the content type of the response:
r->content_type = text/html;
We also add a custom header to the table of headers being sent out:
ap_table_add(r->headers_out, X-Conference, Linux 2000);
Now we send the http header:
ap_send_http_header(r);
It will contain the extra header field that we have specified:
X-Conference: Linux 2000
We then check if the configuration header field exists, and send it to the client using the API function ap_rprintf() if it does:
if (conf->header) { ap_rprintf(r, %s\n, conf->header);
}
After that we have a section which sends data to the client using the API function ap_rputs(), and then the footer field is sent, if it exists. We then return OK, to indicate that we've handled this request.
Linux 2000 Configuration
The source file is compiled into Apache in the same way as our mod_simple example.
Because we've configured these directives to be used inside a , or tag (the ACCESS_CONF field of the command_rec table), we add the following to our configuration file:
SetHandler linux2000-handler
linux2000Header "Linux 2000 Conference"
linux2000Footer "
"
Restart the server:
$ apachectl restart
Our module will now handle all requests to http://server.name/linux2000. We can also configure the content of the header and the footer in the httpd.conf configuration file, using the linux2000Header and linux2000Footer directives.
Apache 2.0
Work is currently underway on the next version of Apache, version 2.0. Some of the features and enhancements we can expect to see in this next release are:
The ability to plug any protocol into Apache, not just HTTP
Filtered I/O: the ability of modules to access other modules data, and more control over the order of modules
Modules providing advanced functionality, such as WebDAV functionality (mod_dav support)
Different startup methods for different platforms (MPM: Multiple-Processing Modules)
More information
Apache Modules Registry
http://modules.apache.org
Design Considerations for the Apache API by Rob Thau
http://www5conf.inria.fr/fich_html/papers/P20/Overview.html
Overview of HTTP
http://www.w3.org/pub/WWW/Protocols
Apache Today
http://apachetoday.com
Apache Week
http://www.apacheweek.com
Acknowledgements
Apache documentation: http://httpd.apache.org/docs
Ryan Bloom, Apache Developer, article at http://apachetoday.com
References
[1] http://www.apache.org
[2] http://xml.apache.org
[3] http://jakarta.apache.org
[4] http://java.apache.org
[5] http://perl.apache.org
[6] http://php.apache.org
[7] http://www.netcraft.com/survey
Addendum One
mod_simple.c source code
#include "httpd.h"
#include "http_protocol.h"
#include "http_config.h"
#include "http_core.h"
#include "http_main.h"
#include
#include
module simple_module;
static int handler_simple(request_rec *r)
{
time_t now;
r->content_type = "text/html";
ap_send_http_header(r);
time(&now);
ap_rputs("\n", r);
ap_rputs("Simple:Time\n", r);
ap_rputs("\n", r);
ap_rprintf(r, "%s
\n\n", ctime(&now));
ap_rputs("\n", r);
return OK;
}
static const handler_rec simple_handler[] = {
{ "simple-handler", handler_simple },
{ NULL }
};
module simple_module = {
STANDARD_MODULE_STUFF,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
simple_handler,
NULL
};
Addendum Two
mod_linux2000.c source code
#include "httpd.h"
#include "http_protocol.h"
#include "http_config.h"
#include "http_core.h"
#include "http_main.h"
#include
module linux2000_module;
typedef struct hf_rec {
char *header;
char *footer;
} hf_rec;
static int handler_linux2000(request_rec *r)
{
hf_rec *conf = (hf_rec *) ap_get_module_config (r->per_dir_config,
&linux2000_module);
r->content_type = "text/html";
ap_table_add(r->headers_out, "X-Conference", "Linux 2000");
ap_send_http_header(r);
if (conf->header) {
ap_rprintf(r, "%s\n", conf->header);
}
ap_rputs("\n", r);
ap_rputs("This is the BODY
\n", r);
if (conf->footer) {
ap_rprintf(r, "%s\n", conf->footer);
}
return OK;
}
static void *linux2000_create_dir_config(pool *p, char *dummy)
{
hf_rec *new = (hf_rec *) ap_pcalloc(p, sizeof(hf_rec));
new->header = NULL;
new->footer = NULL;
return (void *) new;
}
static const char *linux2000_header(cmd_parms *cmd, void *dummy, char *arg)
{
hf_rec *d = dummy;
d->header = ap_pstrdup(cmd->pool, arg);
return NULL;
}
static const char *linux2000_footer(cmd_parms *cmd, void *dummy, char *arg)
{
hf_rec *d = dummy;
d->footer = ap_pstrdup(cmd->pool, arg);
return NULL;
}
static const command_rec linux2000_cmds[] = {
{ "linux2000Header", linux2000_header, NULL, ACCESS_CONF, TAKE1,
"Add a header text to each page" },
{ "linux2000Footer", linux2000_footer, NULL, ACCESS_CONF, TAKE1,
"Add a footer text to each page" },
{ NULL }
};
static const handler_rec linux2000_handler[] = {
{ "linux2000-handler", handler_linux2000 },
{ NULL }
};
module linux2000_module = {
STANDARD_MODULE_STUFF,
NULL,
linux2000_create_dir_config,
NULL,
NULL,
NULL,
linux2000_cmds,
linux2000_handler,
NULL
};
Addendum Three
server_rec structure
struct server_rec {
server_rec *next;
const char *defn_name;
unsigned defn_line_number;
char *srm_confname;
char *access_confname;
char *server_admin;
char *server_hostname;
unsigned short port; /* for redirects, etc. */
char *error_fname;
FILE *error_log;
int loglevel;
int is_virtual; /* true if this is the virtual server */
void *module_config; /* Config vector containing pointers to
* modules' per-server config structures.*/
void *lookup_defaults; /* MIME type info, etc., before we start
* checking per-directory info. */
server_addr_rec *addrs;
int timeout; /* Timeout, in seconds, before we give up */
int keep_alive_timeout; /* Seconds we'll wait for another request */
int keep_alive_max; /* Maximum requests per connection */
int keep_alive; /* Use persistent connections? */
int send_buffer_size; /* size of TCP send buffer (in bytes) */
char *path; /* Pathname for ServerPath */
int pathlen; /* Length of path */
array_header *names; /* Normal names for ServerAlias servers */
array_header *wild_names; /* Wildcarded names for ServerAlias servers */
uid_t server_uid; /* effective user id when calling exec wrapper */
gid_t server_gid; /* effective group id when calling exec wrapper */
int limit_req_line; /* limit on size of the HTTP request line */
int limit_req_fieldsize; /* limit on size of any request header field */
int limit_req_fields; /* limit on number of request header fields */
#ifdef EAPI
ap_ctx *ctx;
#endif /* EAPI */
};
Addendum Four
conn_rec structure
struct conn_rec {
ap_pool *pool;
server_rec *server;
server_rec *base_server; /* Physical vhost this conn come in on */
void *vhost_lookup_data; /* used by http_vhost.c */
/* Information about the connection itself */
int child_num; /* The number of the child handling conn_rec */
BUFF *client; /* Connection to the guy */
struct sockaddr_in local_addr; /* local address */
struct sockaddr_in remote_addr; /* remote address */
char *remote_ip; /* Client's IP address */
char *remote_host; /* Client's DNS name, if known.
* NULL if DNS hasn't been checked,
* "" if it has and no address was found. */
char *remote_logname; /* Only ever set if doing rfc1413 lookups. */
char *user; /* If an authentication check was made,
* this gets set to the user name. We assume
* that there's only one user per connection(!)*/
char *ap_auth_type; /* Ditto. */
unsigned aborted:1; /* Are we still talking? */
signed int keepalive:2; /* Are we using HTTP Keep-Alive?
* -1 fatal error, 0 undecided, 1 yes */
unsigned keptalive:1; /* Did we use HTTP Keep-Alive? */
signed int double_reverse:2; /* have we done double-reverse DNS?
* -1 yes/failure, 0 not yet, 1 yes/success */
int keepalives; /* How many times have we used it? */
char *local_ip; /* server IP address */
char *local_host; /* used for ap_get_server_name when
* UseCanonicalName is set to DNS
* (ignores setting of HostnameLookups) */
#ifdef EAPI
ap_ctx *ctx;
#endif /* EAPI */
};
Addendum Five
request_rec structure
struct request_rec {
ap_pool *pool;
conn_rec *connection;
server_rec *server;
request_rec *next;
request_rec *prev;
request_rec *main;
/* Info about the request itself... we begin with stuff that only
* protocol.c should ever touch... */
char *the_request; /* First line of request, so we can log it */
int assbackwards; /* HTTP/0.9, "simple" request */
enum proxyreqtype proxyreq;
int header_only; /* HEAD request, as opposed to GET */
char *protocol; /* Protocol, as given to us, or HTTP/0.9 */
int proto_num; /* Number version of protocol; 1.1 = 1001 */
const char *hostname; /* Host, as set by full URI or Host: */
time_t request_time; /* When the request started */
const char *status_line; /* Status line, if set by script */
int status; /* In any case */
/* Request method, two ways; also, protocol, etc.. Outside of protocol.c,
* look, but don't touch. */
const char *method; /* GET, HEAD, POST, etc. */
int method_number; /* M_GET, M_POST, etc. */
int allowed; /* Allowed methods - for 405, OPTIONS, etc */
int sent_bodyct; /* byte count in stream is for body */
long bytes_sent; /* body byte count, for easy access */
time_t mtime; /* Time the resource was last modified */
/* HTTP/1.1 connection-level features */
int chunked; /* sending chunked transfer-coding */
int byterange; /* number of byte ranges */
char *boundary; /* multipart/byteranges boundary */
const char *range; /* The Range: header */
long clength; /* The "real" content length */
long remaining; /* bytes left to read */
long read_length; /* bytes that have been read */
int read_body; /* how the request body should be read */
int read_chunked; /* reading chunked transfer-coding */
unsigned expecting_100; /* is client waiting for a 100 response? */
table *headers_in;
table *headers_out;
table *err_headers_out;
table *subprocess_env;
table *notes;
const char *content_type; /* Break these out --- we dispatch on 'em */
const char *handler; /* What we *really* dispatch on */
const char *content_encoding;
const char *content_language; /* for back-compat. only -- do not use */
array_header *content_languages; /* array of (char*) */
char *vlist_validator; /* variant list validator (if negotiated) */
int no_cache;
int no_local_copy;
char *unparsed_uri; /* the uri without any parsing performed */
char *uri; /* the path portion of the URI */
char *filename;
char *path_info;
char *args; /* QUERY_ARGS, if any */
struct stat finfo; /* ST_MODE set to zero if no such file */
uri_components parsed_uri; /* components of uri, dismantled */
void *per_dir_config; /* Options set in config files, etc. */
void *request_config; /* Notes on *this* request */
const struct htaccess_result *htaccess;
char *case_preserved_filename;
#ifdef EAPI
ap_ctx *ctx;
#endif /* EAPI */
};
Addendum Six
POST and GET data
To access POST and GET data, the following function is useful:
static int
my_handler(request_rec *r)
{
char args[HUGE_STRING_LEN];
table *t;
char *p, *key, *val;
int rc, l, size = HUGE_STRING_LEN 1;
t = ap_make_table(r->pool, 50);
ap_add_common_vars(r);
if (r->method_number == M_GET) {
if (r->args && strlen(r->args)) {
memcpy(args, r->args, strlen(r->args));
args[strlen(r->args)] = 0;
}
}
if (r->method_number == M_POST) {
if ( (rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) {
return rc;
}
if (ap_should_client_block(r)) {
while ( (l = ap_get_client_block(r, args, size)) > 0) {
size -= l;
}
}
}
p = args;
while ( *p && (val = ap_getword(r->pool, (const char **) &p, '&'))) {
key = ap_getword(r->pool, (const char **) &val, '=');
ap_unescape_url(key);
ap_unescape_url(val);
ap_table_add(t, key, val);
}
}
- PAGE 6 -
Modules and the Apache Web Server Jason Armstrong
& 0 @ S f g h | } ~ * ǿǛyǿeǛ &j >*B*UmH nH ph u j} UmH nH u j UmH nH umH nH u 0J aJ0 mH nH u&j >*B*UmH nH ph u mH nH u0J mH nH uj 0J UmH nH u mH nH sH u 9:\j 9:U\ CJ aJ mH sH aJ mH sH mH sH &