2009年5月31日 星期日

Request Processing in Apache 2.0請求的處理過程

Apache中HTTP Request的程序主要是request.c中的函數來處理,這個函數是ap_process_request_internal,所有的請求都由它處理,包含子請求(subrequest)和轉向(redirect)。

其程式碼如下所示:


/* This is the master logic for processing requests. Do NOT duplicate
* this logic elsewhere, or the security model will be broken by future
* API changes. Each phase must be individually optimized to pick up
* redundant/duplicate calls by subrequests, and redirects.
*/
AP_DECLARE(int) ap_process_request_internal(request_rec *r)
{
int file_req = (r->main && r->filename);
int access_status;

/* Ignore embedded %2F's in path for proxy requests */
if (!r->proxyreq && r->parsed_uri.path) {
core_dir_config *d;
d = ap_get_module_config(r->per_dir_config, &core_module);
if (d->allow_encoded_slashes) {
access_status = ap_unescape_url_keep2f(r->parsed_uri.path);
}
else {
access_status = ap_unescape_url(r->parsed_uri.path);
}
if (access_status) {
if (access_status == HTTP_NOT_FOUND) {
if (! d->allow_encoded_slashes) {
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
"found %%2f (encoded '/') in URI "
"(decoded='%s'), returning 404",
r->parsed_uri.path);
}
}
return access_status;
}
}

ap_getparents(r->uri); /* OK --- shrinking transformations... */

/* All file subrequests are a huge pain... they cannot bubble through the
* next several steps. Only file subrequests are allowed an empty uri,
* otherwise let translate_name kill the request.
*/
if (!file_req) {
if ((access_status = ap_location_walk(r))) {
return access_status;
}

if ((access_status = ap_run_translate_name(r))) {
return decl_die(access_status, "translate", r);
}
}

/* Reset to the server default config prior to running map_to_storage
*/
r->per_dir_config = r->server->lookup_defaults;

if ((access_status = ap_run_map_to_storage(r))) {
/* This request wasn't in storage (e.g. TRACE) */
return access_status;
}

/* Rerun the location walk, which overrides any map_to_storage config.
*/
if ((access_status = ap_location_walk(r))) {
return access_status;
}

/* Only on the main request! */
if (r->main == NULL) {
if ((access_status = ap_run_header_parser(r))) {
return access_status;
}
}

/* Skip authn/authz if the parent or prior request passed the authn/authz,
* and that configuration didn't change (this requires optimized _walk()
* functions in map_to_storage that use the same merge results given
* identical input.) If the config changes, we must re-auth.
*/
if (r->main && (r->main->per_dir_config == r->per_dir_config)) {
r->user = r->main->user;
r->ap_auth_type = r->main->ap_auth_type;
}
else if (r->prev && (r->prev->per_dir_config == r->per_dir_config)) {
r->user = r->prev->user;
r->ap_auth_type = r->prev->ap_auth_type;
}
else {
switch (ap_satisfies(r)) {
case SATISFY_ALL:
case SATISFY_NOSPEC:
if ((access_status = ap_run_access_checker(r)) != 0) {
return decl_die(access_status, "check access", r);
}

if (ap_some_auth_required(r)) {
if (((access_status = ap_run_check_user_id(r)) != 0)
|| !ap_auth_type(r)) {
return decl_die(access_status, ap_auth_type(r)
? "check user. No user file?"
: "perform authentication. AuthType not set!",
r);
}

if (((access_status = ap_run_auth_checker(r)) != 0)
|| !ap_auth_type(r)) {
return decl_die(access_status, ap_auth_type(r)
? "check access. No groups file?"
: "perform authentication. AuthType not set!",
r);
}
}
break;

case SATISFY_ANY:
if (((access_status = ap_run_access_checker(r)) != 0)) {
if (!ap_some_auth_required(r)) {
return decl_die(access_status, "check access", r);
}

if (((access_status = ap_run_check_user_id(r)) != 0)
|| !ap_auth_type(r)) {
return decl_die(access_status, ap_auth_type(r)
? "check user. No user file?"
: "perform authentication. AuthType not set!",
r);
}

if (((access_status = ap_run_auth_checker(r)) != 0)
|| !ap_auth_type(r)) {
return decl_die(access_status, ap_auth_type(r)
? "check access. No groups file?"
: "perform authentication. AuthType not set!",
r);
}
}
break;
}
}
/* XXX Must make certain the ap_run_type_checker short circuits mime
* in mod-proxy for r->proxyreq && r->parsed_uri.scheme
* && !strcmp(r->parsed_uri.scheme, "http")
*/
if ((access_status = ap_run_type_checker(r)) != 0) {
return decl_die(access_status, "find types", r);
}

if ((access_status = ap_run_fixups(r)) != 0) {
return access_status;
}

return OK;
}

沒有留言:

張貼留言