⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_rewrite.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 5 页
字号:
            /* 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, "[per-dir %s] redirect to %s [REDIRECT/%d]",                       dconf->directory, r->filename, n);            return n;        }        else if (strlen(r->filename) > 10 &&                 strncmp(r->filename, "forbidden:", 10) == 0) {            /* This URL is forced to be forbidden for the requester */            return HTTP_FORBIDDEN;        }        else if (strlen(r->filename) > 5 &&                 strncmp(r->filename, "gone:", 5) == 0) {            /* This URL is forced to be gone */            return HTTP_GONE;        }        else {            /* it was finally rewritten to a local path */            /* if someone used the PASSTHROUGH flag in per-dir             * context we just ignore it. It is only useful             * in per-server context             */            if (strlen(r->filename) > 12 &&                strncmp(r->filename, "passthrough:", 12) == 0) {                r->filename = apr_pstrdup(r->pool, r->filename+12);            }            /* 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;            }            /* Check for deadlooping:             * At this point we KNOW that at least one rewriting             * rule was applied, but when the resulting URL is             * the same as the initial URL, we are not allowed to             * use the following internal redirection stuff because             * this would lead to a deadloop.             */            if (ofilename != NULL && strcmp(r->filename, ofilename) == 0) {                rewritelog(r, 1, "[per-dir %s] initial URL equal rewritten "                           "URL: %s [IGNORING REWRITE]",                           dconf->directory, r->filename);                return OK;            }            /* if there is a valid base-URL then substitute             * the per-dir prefix with this base-URL if the             * current filename still is inside this per-dir             * context. If not then treat the result as a             * plain URL             */            if (dconf->baseurl != NULL) {                rewritelog(r, 2,                           "[per-dir %s] trying to replace prefix %s with %s",                           dconf->directory, dconf->directory, dconf->baseurl);                r->filename = subst_prefix_path(r, r->filename,                                                dconf->directory,                                                dconf->baseurl);            }            else {                /* if no explicit base-URL exists we assume                 * that the directory prefix is also a valid URL                 * for this webserver and only try to remove the                 * document_root if it is prefix                 */                if ((ccp = ap_document_root(r)) != NULL) {                    prefix = apr_pstrdup(r->pool, ccp);                    /* always NOT have a trailing slash */                    l = strlen(prefix);                    if (prefix[l-1] == '/') {                        prefix[l-1] = '\0';                        l--;                    }                    if (strncmp(r->filename, prefix, l) == 0) {                        rewritelog(r, 2,                                   "[per-dir %s] strip document_root "                                   "prefix: %s -> %s",                                   dconf->directory, r->filename,                                   r->filename+l);                        r->filename = apr_pstrdup(r->pool, r->filename+l);                    }                }            }            /* now initiate the internal redirect */            rewritelog(r, 1, "[per-dir %s] internal redirect with %s "                       "[INTERNAL REDIRECT]", dconf->directory, r->filename);            r->filename = apr_pstrcat(r->pool, "redirect:", r->filename, NULL);            r->handler = "redirect-handler";            return OK;        }    }    else {        rewritelog(r, 1, "[per-dir %s] pass through %s",                   dconf->directory, r->filename);        r->filename = ofilename;        return DECLINED;    }}/*****  Content-Handlers****  [used for redirect support]***/static int handler_redirect(request_rec *r){    if (strcmp(r->handler, "redirect-handler")) {        return DECLINED;    }    /* just make sure that we are really meant! */    if (strncmp(r->filename, "redirect:", 9) != 0) {        return DECLINED;    }    if (is_redirect_limit_exceeded(r)) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      "mod_rewrite: maximum number of internal redirects "                      "reached. Assuming configuration error. Use "                      "'RewriteOptions MaxRedirects' to increase the limit "                      "if neccessary.");        return HTTP_INTERNAL_SERVER_ERROR;    }    /* now do the internal redirect */    ap_internal_redirect(apr_pstrcat(r->pool, r->filename+9,                                     r->args ? "?" : NULL, r->args, NULL), r);    /* and return gracefully */    return OK;}/* * check whether redirect limit is reached */static int is_redirect_limit_exceeded(request_rec *r){    request_rec *top = r;    rewrite_request_conf *reqc;    rewrite_perdir_conf *dconf;    /* we store it in the top request */    while (top->main) {        top = top->main;    }    while (top->prev) {        top = top->prev;    }    /* fetch our config */    reqc = (rewrite_request_conf *) ap_get_module_config(top->request_config,                                                         &rewrite_module);    /* no config there? create one. */    if (!reqc) {        rewrite_server_conf *sconf;        reqc = apr_palloc(top->pool, sizeof(rewrite_request_conf));        sconf = ap_get_module_config(r->server->module_config, &rewrite_module);        reqc->redirects = 0;        reqc->redirect_limit = sconf->redirect_limit                                 ? sconf->redirect_limit                                 : REWRITE_REDIRECT_LIMIT;        /* associate it with this request */        ap_set_module_config(top->request_config, &rewrite_module, reqc);    }    /* allow to change the limit during redirects. */    dconf = (rewrite_perdir_conf *)ap_get_module_config(r->per_dir_config,                                                        &rewrite_module);    /* 0 == unset; take server conf ... */    if (dconf->redirect_limit) {        reqc->redirect_limit = dconf->redirect_limit;    }    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,                  "mod_rewrite's internal redirect status: %d/%d.",                  reqc->redirects, reqc->redirect_limit);    /* and now give the caller a hint */    return (reqc->redirects++ >= reqc->redirect_limit);}/*** +-------------------------------------------------------+** |                                                       |** |                  the rewriting engine** |                                                       |** +-------------------------------------------------------+*//* *  Apply a complete rule set, *  i.e. a list of rewrite rules */static int apply_rewrite_list(request_rec *r, apr_array_header_t *rewriterules,                              char *perdir){    rewriterule_entry *entries;    rewriterule_entry *p;    int i;    int changed;    int rc;    int s;    /*     *  Iterate over all existing rules     */    entries = (rewriterule_entry *)rewriterules->elts;    changed = 0;    loop:    for (i = 0; i < rewriterules->nelts; i++) {        p = &entries[i];        /*         *  Ignore this rule on subrequests if we are explicitly         *  asked to do so or this is a proxy-throughput or a         *  forced redirect rule.         */        if (r->main != NULL &&            (p->flags & RULEFLAG_IGNOREONSUBREQ ||             p->flags & RULEFLAG_PROXY          ||             p->flags & RULEFLAG_FORCEREDIRECT    )) {            continue;        }        /*         *  Apply the current rule.         */        rc = apply_rewrite_rule(r, p, perdir);        if (rc) {            /*             *  Indicate a change if this was not a match-only rule.             */            if (rc != 2) {                changed = ((p->flags & RULEFLAG_NOESCAPE)                           ? ACTION_NOESCAPE : ACTION_NORMAL);            }            /*             *  Pass-Through Feature (`RewriteRule .. .. [PT]'):             *  Because the Apache 1.x API is very limited we             *  need this hack to pass the rewritten URL to other             *  modules like mod_alias, mod_userdir, etc.             */            if (p->flags & RULEFLAG_PASSTHROUGH) {                rewritelog(r, 2, "forcing '%s' to get passed through "                           "to next API URI-to-filename handler", r->filename);                r->filename = apr_pstrcat(r->pool, "passthrough:",                                         r->filename, NULL);                changed = ACTION_NORMAL;                break;            }            /*             *  Rule has the "forbidden" flag set which means that             *  we stop processing and indicate this to the caller.             */            if (p->flags & RULEFLAG_FORBIDDEN) {                rewritelog(r, 2, "forcing '%s' to be forbidden", r->filename);                r->filename = apr_pstrcat(r->pool, "forbidden:",                                         r->filename, NULL);                changed = ACTION_NORMAL;                break;            }            /*             *  Rule has the "gone" flag set which means that             *  we stop processing and indicate this to the caller.             */            if (p->flags & RULEFLAG_GONE) {                rewritelog(r, 2, "forcing '%s' to be gone", r->filename);                r->filename = apr_pstrcat(r->pool, "gone:", r->filename, NULL);                changed = ACTION_NORMAL;                break;            }            /*             *  Stop processing also on proxy pass-through and             *  last-rule and new-round flags.             */            if (p->flags & RULEFLAG_PROXY) {                break;            }            if (p->flags & RULEFLAG_LASTRULE) {                break;            }            /*             *  On "new-round" flag we just start from the top of             *  the rewriting ruleset again.             */            if (p->flags & RULEFLAG_NEWROUND) {                goto loop;            }            /*             *  If we are forced to skip N next rules, do it now.             */            if (p->skip > 0) {                s = p->skip;                while (   i < rewriterules->nelts                       && s > 0) {                    i++;                    p = &entries[i];                    s--;                }            }        }        else {            /*             *  If current rule is chained with next rule(s),             *  skip all this next rule(s)             */            while (   i < rewriterules->nelts                   && p->flags & RULEFLAG_CHAIN) {                i++;                p = &entries[i];            }        }    }    return changed;}/* *  Apply a single(!) rewrite rule */static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,                              char *perdir){    char *uri;    char *output;    const char *vary;    char newuri[MAX_STRING_LEN];    regex_t *regexp;    regmatch_t regmatch[AP_MAX_REG_MATCH];    backrefinfo *briRR = NULL;    backrefinfo *briRC = NULL;    int failed;    apr_array_header_t *rewriteconds;    rewritecond_entry *conds;    rewritecond_entry *c;    int i;    int rc;    int is_proxyreq = 0;    /*     *  Initialisation     */    uri     = r->filename;    regexp  = p->regexp;    output  = p->output;    /*     *  Add (perhaps splitted away) PATH_INFO postfix to URL to     *  make sure we really match against the complete URL.     */    if (perdir != NULL && r->path_info != NULL && r->path_info[0] != '\0') {        rewritelog(r, 3, "[per-dir %s] add path info postfix: %s -> %s%s",                   perdir, uri, uri, r->path_in

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -