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

📄 mod_proxy.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 5 页
字号:
    }    return NULL;}static int alias_match(const char *uri, const char *alias_fakename){    const char *end_fakename = alias_fakename + strlen(alias_fakename);    const char *aliasp = alias_fakename, *urip = uri;    const char *end_uri = uri + strlen(uri);    while (aliasp < end_fakename && urip < end_uri) {        if (*aliasp == '/') {            /* any number of '/' in the alias matches any number in             * the supplied URI, but there must be at least one...             */            if (*urip != '/')                return 0;            while (*aliasp == '/')                ++aliasp;            while (*urip == '/')                ++urip;        }        else {            /* Other characters are compared literally */            if (*urip++ != *aliasp++)                return 0;        }    }    /* fixup badly encoded stuff (e.g. % as last character) */    if (aliasp > end_fakename) {        aliasp = end_fakename;    }    if (urip > end_uri) {        urip = end_uri;    }   /* We reach the end of the uri before the end of "alias_fakename"    * for example uri is "/" and alias_fakename "/examples"    */   if (urip == end_uri && aliasp!=end_fakename) {       return 0;   }    /* Check last alias path component matched all the way */    if (aliasp[-1] != '/' && *urip != '\0' && *urip != '/')        return 0;    /* Return number of characters from URI which matched (may be     * greater than length of alias, since we may have matched     * doubled slashes)     */    return urip - uri;}/* Detect if an absoluteURI should be proxied or not.  Note that we * have to do this during this phase because later phases are * "short-circuiting"... i.e. translate_names will end when the first * module returns OK.  So for example, if the request is something like: * * GET http://othervhost/cgi-bin/printenv HTTP/1.0 * * mod_alias will notice the /cgi-bin part and ScriptAlias it and * short-circuit the proxy... just because of the ordering in the * configuration file. */static int proxy_detect(request_rec *r){    void *sconf = r->server->module_config;    proxy_server_conf *conf =        (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);    /* Ick... msvc (perhaps others) promotes ternary short results to int */    if (conf->req && r->parsed_uri.scheme) {        /* but it might be something vhosted */        if (!(r->parsed_uri.hostname              && !strcasecmp(r->parsed_uri.scheme, ap_http_scheme(r))              && ap_matches_request_vhost(r, r->parsed_uri.hostname,                                          (apr_port_t)(r->parsed_uri.port_str ? r->parsed_uri.port                                                       : ap_default_port(r))))) {            r->proxyreq = PROXYREQ_PROXY;            r->uri = r->unparsed_uri;            r->filename = apr_pstrcat(r->pool, "proxy:", r->uri, NULL);            r->handler = "proxy-server";        }    }    /* We need special treatment for CONNECT proxying: it has no scheme part */    else if (conf->req && r->method_number == M_CONNECT             && r->parsed_uri.hostname             && r->parsed_uri.port_str) {        r->proxyreq = PROXYREQ_PROXY;        r->uri = r->unparsed_uri;        r->filename = apr_pstrcat(r->pool, "proxy:", r->uri, NULL);        r->handler = "proxy-server";    }    return DECLINED;}static const char *proxy_interpolate(request_rec *r, const char *str){    /* Interpolate an env str in a configuration string     * Syntax ${var} --> value_of(var)     * Method: replace one var, and recurse on remainder of string     * Nothing clever here, and crap like nested vars may do silly things     * but we'll at least avoid sending the unwary into a loop     */    const char *start;    const char *end;    const char *var;    const char *val;    const char *firstpart;    start = ap_strstr_c(str, "${");    if (start == NULL) {        return str;    }    end = ap_strchr_c(start+2, '}');    if (end == NULL) {        return str;    }    /* OK, this is syntax we want to interpolate.  Is there such a var ? */    var = apr_pstrndup(r->pool, start+2, end-(start+2));    val = apr_table_get(r->subprocess_env, var);    firstpart = apr_pstrndup(r->pool, str, (start-str));    if (val == NULL) {        return apr_pstrcat(r->pool, firstpart,                           proxy_interpolate(r, end+1), NULL);    }    else {        return apr_pstrcat(r->pool, firstpart, val,                           proxy_interpolate(r, end+1), NULL);    }}static apr_array_header_t *proxy_vars(request_rec *r,                                      apr_array_header_t *hdr){    int i;    apr_array_header_t *ret = apr_array_make(r->pool, hdr->nelts,                                             sizeof (struct proxy_alias));    struct proxy_alias *old = (struct proxy_alias *) hdr->elts;    for (i = 0; i < hdr->nelts; ++i) {        struct proxy_alias *newcopy = apr_array_push(ret);        newcopy->fake = (old[i].flags & PROXYPASS_INTERPOLATE)                        ? proxy_interpolate(r, old[i].fake) : old[i].fake;        newcopy->real = (old[i].flags & PROXYPASS_INTERPOLATE)                        ? proxy_interpolate(r, old[i].real) : old[i].real;    }    return ret;}static int proxy_trans(request_rec *r){    void *sconf = r->server->module_config;    proxy_server_conf *conf =    (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);    int i, len;    struct proxy_alias *ent = (struct proxy_alias *) conf->aliases->elts;    proxy_dir_conf *dconf = ap_get_module_config(r->per_dir_config,                                                 &proxy_module);    const char *fake;    const char *real;    ap_regmatch_t regm[AP_MAX_REG_MATCH];    ap_regmatch_t reg1[AP_MAX_REG_MATCH];    char *found = NULL;    int mismatch = 0;    if (r->proxyreq) {        /* someone has already set up the proxy, it was possibly ourselves         * in proxy_detect         */        return OK;    }    /* XXX: since r->uri has been manipulated already we're not really     * compliant with RFC1945 at this point.  But this probably isn't     * an issue because this is a hybrid proxy/origin server.     */    for (i = 0; i < conf->aliases->nelts; i++) {        unsigned int nocanon = ent[i].flags & PROXYPASS_NOCANON;        const char *use_uri = nocanon ? r->unparsed_uri : r->uri;        if ((dconf->interpolate_env == 1)            && (ent[i].flags & PROXYPASS_INTERPOLATE)) {            fake = proxy_interpolate(r, ent[i].fake);            real = proxy_interpolate(r, ent[i].real);        }        else {            fake = ent[i].fake;            real = ent[i].real;        }        if (ent[i].regex) {            if (!ap_regexec(ent[i].regex, r->uri, AP_MAX_REG_MATCH, regm, 0)) {                if ((real[0] == '!') && (real[1] == '\0')) {                    return DECLINED;                }                /* test that we haven't reduced the URI */                if (nocanon && ap_regexec(ent[i].regex, r->unparsed_uri,                                          AP_MAX_REG_MATCH, reg1, 0)) {                    mismatch = 1;                    use_uri = r->uri;                }                found = ap_pregsub(r->pool, real, use_uri, AP_MAX_REG_MATCH,                                   (use_uri == r->uri) ? regm : reg1);                /* Note: The strcmp() below catches cases where there                 * was no regex substitution. This is so cases like:                 *                 *    ProxyPassMatch \.gif balancer://foo                 *                 * will work "as expected". The upshot is that the 2                 * directives below act the exact same way (ie: $1 is implied):                 *                 *    ProxyPassMatch ^(/.*\.gif)$ balancer://foo                 *    ProxyPassMatch ^(/.*\.gif)$ balancer://foo$1                 *                 * which may be confusing.                 */                if (found && strcmp(found, real)) {                    found = apr_pstrcat(r->pool, "proxy:", found, NULL);                }                else {                    found = apr_pstrcat(r->pool, "proxy:", real,                                        use_uri, NULL);                }            }        }        else {            len = alias_match(r->uri, fake);            if (len != 0) {                if ((real[0] == '!') && (real[1] == '\0')) {                    return DECLINED;                }                if (nocanon                    && len != alias_match(r->unparsed_uri, ent[i].fake)) {                    mismatch = 1;                    use_uri = r->uri;                }                found = apr_pstrcat(r->pool, "proxy:", real,                                    use_uri + len, NULL);            }        }        if (mismatch) {            /* We made a reducing transformation, so we can't safely use             * unparsed_uri.  Safe fallback is to ignore nocanon.             */            ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,                          "Unescaped URL path matched ProxyPass; ignoring unsafe nocanon");        }        if (found) {            r->filename = found;            r->handler = "proxy-server";            r->proxyreq = PROXYREQ_REVERSE;            if (nocanon && !mismatch) {                /* mod_proxy_http needs to be told.  Different module. */                apr_table_setn(r->notes, "proxy-nocanon", "1");            }            return OK;        }    }    return DECLINED;}static int proxy_walk(request_rec *r){    proxy_server_conf *sconf = ap_get_module_config(r->server->module_config,                                                    &proxy_module);    ap_conf_vector_t *per_dir_defaults = r->server->lookup_defaults;    ap_conf_vector_t **sec_proxy = (ap_conf_vector_t **) sconf->sec_proxy->elts;    ap_conf_vector_t *entry_config;    proxy_dir_conf *entry_proxy;    int num_sec = sconf->sec_proxy->nelts;    /* XXX: shouldn't we use URI here?  Canonicalize it first?     * Pass over "proxy:" prefix     */    const char *proxyname = r->filename + 6;    int j;    for (j = 0; j < num_sec; ++j)    {        entry_config = sec_proxy[j];        entry_proxy = ap_get_module_config(entry_config, &proxy_module);        /* XXX: What about case insensitive matching ???         * Compare regex, fnmatch or string as appropriate         * If the entry doesn't relate, then continue         */        if (entry_proxy->r              ? ap_regexec(entry_proxy->r, proxyname, 0, NULL, 0)              : (entry_proxy->p_is_fnmatch                   ? apr_fnmatch(entry_proxy->p, proxyname, 0)                   : strncmp(proxyname, entry_proxy->p,                                        strlen(entry_proxy->p)))) {            continue;        }        per_dir_defaults = ap_merge_per_dir_configs(r->pool, per_dir_defaults,                                                             entry_config);    }    r->per_dir_config = per_dir_defaults;    return OK;}static int proxy_map_location(request_rec *r){    int access_status;    if (!r->proxyreq || !r->filename || strncmp(r->filename, "proxy:", 6) != 0)        return DECLINED;    /* Don't let the core or mod_http map_to_storage hooks handle this,     * We don't need directory/file_walk, and we want to TRACE on our own.     */    if ((access_status = proxy_walk(r))) {        ap_die(access_status, r);        return access_status;    }    return OK;}/* -------------------------------------------------------------- *//* Fixup the filename *//* * Canonicalise the URL */static int proxy_fixup(request_rec *r){    char *url, *p;    int access_status;    proxy_dir_conf *dconf = ap_get_module_config(r->per_dir_config,                                                 &proxy_module);    if (!r->proxyreq || !r->filename || strncmp(r->filename, "proxy:", 6) != 0)        return DECLINED;    /* XXX: Shouldn't we try this before we run the proxy_walk? */    url = &r->filename[6];    if ((dconf->interpolate_env == 1) && (r->proxyreq == PROXYREQ_REVERSE)) {        /* create per-request copy of reverse proxy conf,         * and interpolate vars in it         */        proxy_req_conf *rconf = apr_palloc(r->pool, sizeof(proxy_req_conf));        ap_set_module_config(r->request_config, &proxy_module, rconf);        rconf->raliases = proxy_vars(r, dconf->raliases);        rconf->cookie_paths = proxy_vars(r, dconf->cookie_paths);        rconf->cookie_domains = proxy_vars(r, dconf->cookie_domains);    }    /* canonicalise each specific scheme */    if ((access_status = proxy_run_canon_handler(r, url))) {        return access_status;    }    p = strchr(url, ':');    if (p == NULL || p == url)        return HTTP_BAD_REQUEST;    return OK;      /* otherwise; we've done the best we can */}/* Send a redirection if the request contains a hostname which is not *//* fully qualified, i.e. doesn't have a domain name appended. Some proxy */

⌨️ 快捷键说明

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