Translate Name
int module_translate(request_rec *pReq)
This function’s task is to
translate the URL in a request into a filename. The end result of its
deliberations should be placed in
pReq->filename
. It should return
OK
, DECLINED
, or a status code.
The first module that doesn’t return
DECLINED
is assumed to have done the job, and no
further modules are called. Since the order in which modules are
called is not defined, it is a good thing if the URLs handled by the
modules are mutually exclusive. If all modules return
DECLINED
, a configuration error has occurred.
Obviously, the function is likely to use the per-directory and
per-server configurations (but note that at this stage, the
per-directory configuration refers to the root configuration of the
current server) to determine whether it should handle the request, as
well as the URL itself (in pReq->uri
). If a
status is returned, the appropriate headers for the response should
also be set in pReq->headers_out
.
Naturally enough, Example 21-14 (1.3 and 2.0) comes from mod_alias.c:
Example 21-14. mod_alias.c
static char *try_alias_list(request_rec *r, array_header *aliases, int doesc, int *status) { alias_entry *entries = (alias_entry *) aliases->elts; regmatch_t regm[10]; char *found = NULL; int i; for (i = 0; i < aliases->nelts; ++i) { alias_entry *p = &entries[i]; int l; if (p->regexp) { if (!ap_regexec(p->regexp, r->uri, p->regexp->re_nsub + 1, regm, 0)) { if (p->real) { found = ap_pregsub(r->pool, p->real, r->uri, p->regexp->re_nsub + 1, regm); if (found && doesc) { found = ap_escape_uri(r->pool, found); } } else { /* need something non-null */ found = ap_pstrdup(r->pool, ""); } } } else { l = alias_matches(r->uri, p->fake); if (l > 0) { if (doesc) { char *escurl; escurl = ap_os_escape_path(r->pool, r->uri + l, 1); found = ap_pstrcat(r->pool, p->real, escurl, NULL); } else found = ap_pstrcat(r->pool, p->real, r->uri + l, NULL); } } if (found) { if (p->handler) { /* Set handler, and leave a note for mod_cgi */ r->handler = p->handler; ap_table_setn(r->notes, "alias-forced-type", r->handler); } *status = p->redir_status; return found; } } return NULL; } static int translate_alias_redir(request_rec *r) { void *sconf = r->server->module_config; alias_server_conf *serverconf = (alias_server_conf *) ap_get_module_config(sconf, &alias_module); char *ret; int status; if (r->uri[0] != '/' && r->uri[0] != '\0') return DECLINED; if ((ret = try_alias_list(r, serverconf->redirects, 1, &status)) != NULL) { if (ap_is_HTTP_REDIRECT(status)) { /* include QUERY_STRING if any */ if (r->args) { ret = ap_pstrcat(r->pool, ret, "?", r->args, NULL); } ap_table_setn(r->headers_out, "Location", ret); } return status; } if ((ret = try_alias_list(r, serverconf->aliases, 0, &status)) != NULL) { r->filename = ret; return OK; } return DECLINED; }
First of all, this example tries to match a
Redirect
directive. If it does, the
Location
header is set in
headers_out
, and REDIRECT
is
returned. If not, it translates into a filename. Note that it may
also set a handler (in fact, the only handler it can possibly set is
cgi-script, which it does if the alias was
created by a ScriptAlias
directive). An
interesting feature is that it sets a note for
mod_cgi.c, namely
alias-forced-type. This is used by
mod_cgi.c to determine whether the CGI script is
invoked via a ScriptAlias
, in which case
Options
ExecCGI
is not
needed.[5] For completeness, here is the code from
mod_cgi.c that makes the test:
int is_scriptaliased (request_rec *r) { char *t = table_get (r->notes, "alias-forced-type"); return t && (!strcmp (t, "cgi-script")); }
At this point, the filename is known as well as the URL, and Apache reconfigures itself to hand subsequent module functions the relevant per-directory configuration (actually composed of all matching directory, location, and file configurations, merged with each other via the per-directory merger, in that order).[6]
[5] This is a backward-compatibility feature.
[6] In fact, some of this is done before the Translate Name phase, and some after, since the location information can be used before name translation is done, but filename information obviously cannot be. If you really want to know exactly what is going on, probe the behavior with mod_reveal.c.