From: Rich Bowen Warning - this is a first (fast) draft that needs further
- revision! Several changes in 2.0 and above 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
- the Apache HTTP Server 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 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 1.3) without introducing fragile or
- insecure code. This document describes how the Apache HTTP Server processes
+ requests internally, covering the full hook sequence from URI
+ translation through content generation and logging. Module authors
+ should understand these phases to correctly insert their processing
+ at the appropriate point in the cycle. All requests pass through
+ The first major design principle is that all request processing
+ paths (main requests, subrequests, and redirects) share a single
+ code path. Duplicate code was folded back into
+ To streamline requests, module authors can take advantage of
+ the hooks offered to drop
+ out of the request cycle early, or to bypass core hooks which are
+ irrelevant (and costly in terms of CPU). All requests pass through 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 hooks which are
- irrelevant (and costly in terms of CPU.) The complete request processing cycle involves the following hooks,
+ listed in execution order. Hooks marked with (request.c) are
+ implemented in Additionally, the dirwalk_stat
+ hook is called during directory walks to allow modules to emulate or
+ override Before hooks run, the server performs URL normalization: The request's This step is bypassed if the proxyreq flag is set, or the
All This step cannot be bypassed. Every request is subject to an
The This hook is declared in The Used by: Return Called when a new This is a Used by: Runs before URL decoding happens. Modules can manipulate the
+ raw URI before it is translated to a filesystem path. This is
+ useful for modules that need to operate on the URI before
+ percent-decoding or normalization. Return Used by: Modules can determine the file name, or alter the given URI
in this step. For example, If all modules After the file or correct URI was determined, the
- appropriate per-dir configurations are merged together. For
- example, Every request is hardened by a second
- The main request then parses the client's headers. This
- prepares the remaining request processing steps to better serve
- the client's request. Needs Documentation. Code is: After the file or correct URI was determined, the
+ appropriate per-dir configurations are merged together. For
+ example, If no module answers this hook with After This hook fires immediately after per-directory configuration has been
+ merged (after both Return The main request then parses the client's headers. This
+ prepares the remaining request processing steps to better serve
+ the client's request. This hook only runs for the initial
+ request (not subrequests). The security phase in 2.4+ uses the "new" provider-based
+ authentication/authorization architecture managed by
+ The hooks execute in this order: Parses any tokens in the request (e.g. bearer tokens, API keys)
+ that contain metadata such as user identities or IP addresses
+ relevant to the request. Runs before the access checker. If this hook returns This hook is available in trunk only (not backported to 2.4
+ at the time of writing). Applies additional access control to the resource. This hook runs
+ before a user is authenticated, so it is for restrictions
+ independent of user identity (e.g. IP-based access, time-of-day
+ restrictions). It runs independent of This is a Extended access control that runs after Return Allows a module to force authentication to be required even when
+ Return Authenticates the user â analyzes the request headers, validates
+ credentials, and sets Modules should register using Checks whether the authenticated user ( Modules should register using ap_process_request_internal() to prevent
- the code from falling out of sync again.ap_process_request_internal() in
+ server/request.c, including subrequests and internal
+ redirects. Do not duplicate this logic elsewhere; doing so will
+ break when the request processing API changes.ap_process_request_internal() in 2.0 to prevent the
+ paths from falling out of sync.ap_process_request_internal()
- in server/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.server/request.c; others are declared
+ in http_config.h or http_protocol.h and
+ run from the MPM or protocol layer.
+
+
+ r->user)apr_stat() calls.parsed_uri path is unescaped, once and only
once, at the beginning of internal request processing.parsed_uri.path element is unset. The module has no further
- control of this one-time unescape operation, either failing to
+ control of this one-time unescape operation; either failing to
unescape or multiply unescaping the URL leads to security
repercussions./../ and /./ elements are
- removed by ap_getparents(), as well as any trailing
+ removed by ap_getparents(), as well as any trailing
/. or /.. element. This helps to ensure
the path is (nearly) absolute before the request processing
continues. (See RFC 1808 section 4 for further discussion.)ap_location_walk() call. This ensures that
quick_handler hook runs before any other
+ request processing hooks â before location walks, directory walks,
+ access checking, and authentication. It provides a fast path for
+ modules that can serve content directly from a URI-keyed cache or
+ similar mechanism without needing per-directory configuration.http_config.h and called from
+ the MPM/protocol layer, not from
+ ap_process_request_internal().lookup_uri parameter is set to 1 when called from
+ ap_sub_req_lookup_uri(), indicating the caller only needs
+ metadata (not actual content delivery).OK to indicate the request has been fully handled.
+ Return DECLINED to fall through to normal processing.request_rec is created (for main
+ requests, subrequests, and internal redirects). Modules use this hook
+ to initialize per-request module state and set up private data
+ structures attached to the request pool or request notes.RUN_ALL hook â all registered modules get
+ a chance to run. Return OK or DECLINED.DECLINED to let other modules handle the
+ pre-translation, OK if it was handled, DONE
+ if no further transformation should happen on the URI, or an
+ HTTP error status code.DECLINE this phase, an error 500 is
returned to the browser, and a "couldn't translate name" error is logged
automatically.TRACE
- request, the core handles the request and returns DONE.
- If no module answers this hook with OK or DONE,
- the core will run the request filename against the ap_location_walk() call. This reassures that a
- translated request is still subjected to the configured
- location_walk above, so this step is almost always very
- efficient unless the translated URI mapped to a substantially different
- path or Virtual Host.TRACE
+ request, the core handles the request and returns DONE.OK or DONE,
+ the core will run the request filename against the map_to_storage, a second
+ ap_location_walk() call hardens the request by re-applying
+ map_to_storage and the second location
+ walk). Modules can use it to act on the fully-merged per-directory
+ configuration before access control runs.OK to allow processing to continue,
+ DECLINED to let later modules decide, or an HTTP
+ error status code to abort.OK under Satisfy any,
+ the request is authorized immediately without running further
+ access/auth hooks.RUN_ALL hook â all registered modules run.
+ Return OK to allow, or an HTTP error status to deny.access_checker
+ but before user authentication. This hook can also bypass
+ authentication entirely by returning OK â used by
+ Require directives can grant access
+ without credentials (e.g. Require ip).OK to grant access (skipping authn unless
+ force_authn overrides), DECLINED to
+ require authentication, or an HTTP error status to deny.access_checker_ex has already granted access. This is
+ useful when a module needs the authenticated user identity for
+ purposes beyond authorization (e.g. logging, personalization).OK to force authentication, or
+ DECLINED to let later modules decide.r->user and
+ r->ap_auth_type. This hook only runs when Apache
+ determines that authentication is required for this resource.ap_hook_check_authn()
+ rather than hooking check_user_id directly.r->user)
+ is authorized to access this resource. Runs after
+ check_user_id, and only when a ap_hook_check_authz()
+ rather than hooking auth_checker directly.
If all modules DECLINE this phase, an error 500 is
returned to the browser, and a "couldn't find types" error is logged
automatically.
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.
+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 is the last + hook to run before content generation.
+ +This is a RUN_ALL hook â all registered modules
+ get a chance to run. Used by
This phase is not part of the processing in
- ap_process_request_internal(). Many
- modules prepare one or more subrequests prior to creating any
- content at all. After the core, or a module calls
- ap_process_request_internal() it then calls
+ ap_process_request_internal(). After the core or a module
+ calls ap_process_request_internal(), it then calls
ap_invoke_handler() to generate the request.
Modules that transform the content in some way can insert their values and override existing filters, such that if the user configured a more advanced filter out-of-order, then the - module can move its order as need be. There is no result code, - so actions in this hook better be trusted to always succeed.
+ module can move its order as needed. There is no result code, + so actions in this hook must always succeed. + +This is a VOID hook â no return value. Used by
+
After the response has been sent to the client, modules can
+ perform logging activities. This hook is declared in
+ http_protocol.h and runs outside of
+ ap_process_request_internal().
Used by:
Return OK or DECLINED. Errors at
+ this stage do not affect the client response (it has already
+ been sent).
This hook is called during directory walks to allow modules to
+ handle or emulate the apr_stat() calls needed to
+ traverse the filesystem. This enables modules to serve content
+ from non-filesystem backends (databases, remote storage, etc.)
+ while still participating in the directory walk mechanism.
Return an apr_status_t value, or
+ AP_DECLINED to let later modules (or the default
+ apr_stat() call) decide.
Each hook uses one of the following execution strategies:
+ +RUN_FIRSTDECLINED. Used by: pre_translate_name,
+ translate_name, map_to_storage,
+ check_user_id, type_checker,
+ access_checker_ex, auth_checker,
+ force_authn, token_checker,
+ dirwalk_stat.RUN_ALLfixups, access_checker,
+ create_request, post_perdir_config.VOIDinsert_filter.Modules control their position in the hook chain using the
+ order, predecessors, and
+ successors arguments to the ap_hook_*
+ registration functions. See the
+ module guide for details.