Apache 2.0 对请求的处理
Warning
Warning - this is a first (fast) draft that needs further revision!
Several changes in Apache 2.0 affect the internal request processing mechanics. Module authors need to be aware of these changes so they may take advantage of the optimizations and security enhancements.
The first major change is to the subrequest and redirect
mechanisms. There were a number of different code paths in
Apache 1.3 to attempt to optimize subrequest or redirect
behavior. As patches were introduced to 2.0, these
optimizations (and the server behavior) were quickly broken due
to this duplication of code. All duplicate code has been folded
back into ap_process_request_internal()
to prevent
the code from falling out of sync again.
This means that much of the existing code was 'unoptimized'. It is the Apache HTTP Project's first goal to create a robust and correct implementation of the HTTP server RFC. Additional goals include security, scalability and optimization. New methods were sought to optimize the server (beyond the performance of Apache 1.3) without introducing fragile or insecure code.
The Request Processing Cycle
All requests pass through ap_process_request_internal()
in request.c
, including subrequests and redirects. If a module
doesn't pass generated requests through this code, the author is cautioned
that the module may be broken by future changes to request
processing.
To streamline requests, the module author can take advantage of the hooks offered to drop out of the request cycle early, or to bypass core Apache hooks which are irrelevant (and costly in terms of CPU.)
<Location> sections
are consistently enforced for all requests. If the request is an internal
redirect or a sub-request, it may borrow some or all of the processing
from the previous or parent request's ap_location_walk, so this step
is generally very efficient after processing the main request.
mod_vhost_alias will
translate the URI's path into the configured virtual host,
mod_alias
will translate the path to an alias path,
and if the request falls back on the core, the DocumentRoot
is prepended to the request resource.
mod_alias
will translate the path to an alias path,
and if the request falls back on the core, the DocumentRoot
is prepended to the request resource.
If all modules DECLINE
this phase, an error 500 is
returned to the browser, and a "couldn't translate name" error is logged
automatically.
mod_proxy compares and merges the appropriate
<Proxy>
sections.
If the URI is nothing more than a local (non-proxy) TRACE
request, the core handles the request and returns DONE
.
If no module answers this hook with OK
或DONE
,
the core will run the request filename against the <Directory>
和<Files>
sections. If the request
'filename' isn't an absolute, legal filename, a note is set for
later termination.
<Location> sections.
The request again borrows some or all of the processing from its previous
location_walk
above, so this step is almost always very
efficient unless the translated URI mapped to a substantially different
path or Virtual Host.
Hook: header_parser
location_walk
above, so this step is almost always very
efficient unless the translated URI mapped to a substantially different
path or Virtual Host.
Hook: header_parser
The main request then parses the client's headers. This prepares the remaining request processing steps to better serve the client's request.
The Security Phase
Needs Documentation. Code is:
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; }
mod_mime和mod_mime_magic
use this phase to compare the file
name or contents against the administrator's configuration and set the
content type, language, character set and request handler. Some modules
may set up their filters or other request handling parameters at this
time.
If all modules DECLINE
this phase, an error 500 is
returned to the browser, and a "couldn't find types" error is logged
automatically.
Hook: fixups
Many modules are 'trounced' by some phase above. The fixups phase is used by modules to 'reassert' their ownership or force the request's fields to their appropriate values. It isn't always the cleanest mechanism, but occasionally it's the only option.