📄 mod_rewrite.c
字号:
/* * now apply the rules ... */ rulestatus = apply_rewrite_list(r, conf->rewriterules, NULL); apr_table_set(r->notes,"mod_rewrite_rewritten", apr_psprintf(r->pool,"%d",rulestatus)); } else { rewritelog(r, 2, "uri already rewritten. Status %s, Uri %s, r->filename %s", saved_rulestatus, r->uri, r->filename); rulestatus = atoi(saved_rulestatus); } if (rulestatus) { unsigned skip; if (strlen(r->filename) > 6 && strncmp(r->filename, "proxy:", 6) == 0) { /* it should be go on as an internal proxy request */ /* check if the proxy module is enabled, so * we can actually use it! */ if (!proxy_available) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "attempt to make remote request from mod_rewrite " "without proxy enabled: %s", r->filename); return HTTP_FORBIDDEN; } /* make sure the QUERY_STRING and * PATH_INFO parts get incorporated */ if (r->path_info != NULL) { r->filename = apr_pstrcat(r->pool, r->filename, r->path_info, NULL); } if (r->args != NULL && r->uri == r->unparsed_uri) { /* see proxy_http:proxy_http_canon() */ r->filename = apr_pstrcat(r->pool, r->filename, "?", r->args, NULL); } /* now make sure the request gets handled by the proxy handler */ if (PROXYREQ_NONE == r->proxyreq) { r->proxyreq = PROXYREQ_REVERSE; } r->handler = "proxy-server"; rewritelog(r, 1, "go-ahead with proxy request %s [OK]", r->filename); return OK; } else if ((skip = is_absolute_uri(r->filename)) > 0) { /* it was finally rewritten to a remote URL */ if (rulestatus != ACTION_NOESCAPE) { rewritelog(r, 1, "escaping %s for redirect", r->filename); r->filename = escape_absolute_uri(r->pool, r->filename, skip); } /* append the QUERY_STRING part */ if (r->args) { r->filename = apr_pstrcat(r->pool, r->filename, "?", (rulestatus == ACTION_NOESCAPE) ? r->args : ap_escape_uri(r->pool, r->args), NULL); } /* determine HTTP redirect response code */ if (ap_is_HTTP_REDIRECT(r->status)) { n = r->status; r->status = HTTP_OK; /* make Apache kernel happy */ } else { n = HTTP_MOVED_TEMPORARILY; } /* now do the redirection */ apr_table_setn(r->headers_out, "Location", r->filename); rewritelog(r, 1, "redirect to %s [REDIRECT/%d]", r->filename, n); return n; } else if (strlen(r->filename) > 10 && strncmp(r->filename, "forbidden:", 10) == 0) { /* This URLs is forced to be forbidden for the requester */ return HTTP_FORBIDDEN; } else if (strlen(r->filename) > 5 && strncmp(r->filename, "gone:", 5) == 0) { /* This URLs is forced to be gone */ return HTTP_GONE; } else if (strlen(r->filename) > 12 && strncmp(r->filename, "passthrough:", 12) == 0) { /* * Hack because of underpowered API: passing the current * rewritten filename through to other URL-to-filename handlers * just as it were the requested URL. This is to enable * post-processing by mod_alias, etc. which always act on * r->uri! The difference here is: We do not try to * add the document root */ r->uri = apr_pstrdup(r->pool, r->filename+12); return DECLINED; } else { /* it was finally rewritten to a local path */ /* expand "/~user" prefix */#if APR_HAS_USER r->filename = expand_tildepaths(r, r->filename);#endif rewritelog(r, 2, "local path result: %s", r->filename); /* the filename must be either an absolute local path or an * absolute local URL. */ if ( *r->filename != '/' && !ap_os_is_path_absolute(r->pool, r->filename)) { return HTTP_BAD_REQUEST; } /* if there is no valid prefix, we have * to emulate the translator from the core and * prefix the filename with document_root * * NOTICE: * We cannot leave out the prefix_stat because * - when we always prefix with document_root * then no absolute path can be created, e.g. via * emulating a ScriptAlias directive, etc. * - when we always NOT prefix with document_root * then the files under document_root have to * be references directly and document_root * gets never used and will be a dummy parameter - * this is also bad * * BUT: * Under real Unix systems this is no problem, * because we only do stat() on the first directory * and this gets cached by the kernel for along time! */ n = prefix_stat(r->filename, r->pool); if (n == 0) { if ((ccp = ap_document_root(r)) != NULL) { l = apr_cpystrn(docroot, ccp, sizeof(docroot)) - docroot; /* always NOT have a trailing slash */ if (docroot[l-1] == '/') { docroot[l-1] = '\0'; } if (r->server->path && !strncmp(r->filename, r->server->path, r->server->pathlen)) { r->filename = apr_pstrcat(r->pool, docroot, (r->filename + r->server->pathlen), NULL); } else { r->filename = apr_pstrcat(r->pool, docroot, r->filename, NULL); } rewritelog(r, 2, "prefixed with document_root to %s", r->filename); } } rewritelog(r, 1, "go-ahead with %s [OK]", r->filename); return OK; } } else { rewritelog(r, 1, "pass through %s", r->filename); return DECLINED; }}/***** MIME-type hook**** [used to support the forced-MIME-type feature]***/static int hook_mimetype(request_rec *r){ const char *t; /* now check if we have to force a MIME-type */ t = apr_table_get(r->notes, REWRITE_FORCED_MIMETYPE_NOTEVAR); if (t == NULL) { return DECLINED; } else { rewritelog(r, 1, "force filename %s to have MIME-type '%s'", r->filename, t); ap_set_content_type(r, t); return OK; }}/***** Fixup hook**** [used for the rewriting engine triggered by** the per-directory 'RewriteRule' directives]***/static int hook_fixup(request_rec *r){ rewrite_perdir_conf *dconf; char *cp; char *cp2; const char *ccp; char *prefix; apr_size_t l; int rulestatus; int n; char *ofilename; int is_proxyreq; dconf = (rewrite_perdir_conf *)ap_get_module_config(r->per_dir_config, &rewrite_module); /* if there is no per-dir config we return immediately */ if (dconf == NULL) { return DECLINED; } /* we shouldn't do anything in subrequests */ if (r->main != NULL) { return DECLINED; } /* if there are no real (i.e. no RewriteRule directives!) per-dir config of us, we return also immediately */ if (dconf->directory == NULL) { return DECLINED; } /* * Proxy request? */ is_proxyreq = ( r->proxyreq && r->filename && !strncmp(r->filename, "proxy:", 6)); /* * .htaccess file is called before really entering the directory, i.e.: * URL: http://localhost/foo and .htaccess is located in foo directory * Ignore such attempts, since they may lead to undefined behaviour. */ if (is_proxyreq) { l = strlen(dconf->directory) - 1; if (r->filename && strlen(r->filename) == l && (dconf->directory)[l] == '/' && !strncmp(r->filename, dconf->directory, l)) { return DECLINED; } } /* * only do something under runtime if the engine is really enabled, * for this directory, else return immediately! */ if (dconf->state == ENGINE_DISABLED) { return DECLINED; } /* * Do the Options check after engine check, so * the user is able to explicitely turn RewriteEngine Off. */ if (!(ap_allow_options(r) & (OPT_SYM_LINKS | OPT_SYM_OWNER))) { /* FollowSymLinks is mandatory! */ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Options FollowSymLinks or SymLinksIfOwnerMatch is off " "which implies that RewriteRule directive is forbidden: " "%s", r->filename); return HTTP_FORBIDDEN; } /* * remember the current filename before rewriting for later check * to prevent deadlooping because of internal redirects * on final URL/filename which can be equal to the inital one. * also, we'll restore original r->filename if we decline this * request */ ofilename = r->filename; if (r->filename == NULL) { r->filename = apr_pstrdup(r->pool, r->uri); rewritelog(r, 2, "init rewrite engine with requested uri %s", r->filename); } /* * now apply the rules ... */ rulestatus = apply_rewrite_list(r, dconf->rewriterules, dconf->directory); if (rulestatus) { unsigned skip; if (strlen(r->filename) > 6 && strncmp(r->filename, "proxy:", 6) == 0) { /* it should go on as an internal proxy request */ /* make sure the QUERY_STRING and * PATH_INFO parts get incorporated * (r->path_info was already appended by the * rewriting engine because of the per-dir context!) */ if (r->args != NULL) { r->filename = apr_pstrcat(r->pool, r->filename, "?", r->args, NULL); } /* now make sure the request gets handled by the proxy handler */ if (PROXYREQ_NONE == r->proxyreq) { r->proxyreq = PROXYREQ_REVERSE; } r->handler = "proxy-server"; rewritelog(r, 1, "[per-dir %s] go-ahead with proxy request " "%s [OK]", dconf->directory, r->filename); return OK; } else if ((skip = is_absolute_uri(r->filename)) > 0) { /* it was finally rewritten to a remote URL */ /* because we are in a per-dir context * first try to replace the directory with its base-URL * if there is a base-URL available */ if (dconf->baseurl != NULL) { /* skip 'scheme://' */ cp = r->filename + skip; if ((cp = ap_strchr(cp, '/')) != NULL && *(++cp)) { rewritelog(r, 2, "[per-dir %s] trying to replace " "prefix %s with %s", dconf->directory, dconf->directory, dconf->baseurl); /* I think, that hack needs an explanation: * well, here is it: * mod_rewrite was written for unix systems, were * absolute file-system paths start with a slash. * URL-paths _also_ start with slashes, so they * can be easily compared with system paths. * * the following assumes, that the actual url-path * may be prefixed by the current directory path and * tries to replace the system path with the RewriteBase * URL. * That assumption is true if we use a RewriteRule like * * RewriteRule ^foo bar [R] * * (see apply_rewrite_rule function) * However on systems that don't have a / as system * root this will never match, so we skip the / after the * hostname and compare/substitute only the stuff after it. * * (note that cp was already increased to the right value) */ cp2 = subst_prefix_path(r, cp, (*dconf->directory == '/') ? dconf->directory + 1 : dconf->directory, dconf->baseurl + 1); if (strcmp(cp2, cp) != 0) { *cp = '\0'; r->filename = apr_pstrcat(r->pool, r->filename, cp2, NULL); } } } /* now prepare the redirect... */ if (rulestatus != ACTION_NOESCAPE) { rewritelog(r, 1, "[per-dir %s] escaping %s for redirect", dconf->directory, r->filename); r->filename = escape_absolute_uri(r->pool, r->filename, skip); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -