mod_proxy.c

来自「apache服务器源代码(版本号:2.2.2)」· C语言 代码 · 共 1,862 行 · 第 1/5 页

C
1,862
字号
            }        }        /* otherwise, try it direct */        /* N.B. what if we're behind a firewall, where we must use a proxy or        * give up??        */        /* handle the scheme */        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                     "Running scheme %s handler (attempt %d)",                     scheme, attempts);        access_status = proxy_run_scheme_handler(r, worker, conf,                                                 url, NULL, 0);        if (access_status == OK)            break;        else if (access_status == HTTP_INTERNAL_SERVER_ERROR) {            /* Unrecoverable server error.             * We can not failover to another worker.             * Mark the worker as unusable if member of load balancer             */            if (balancer)                worker->s->status |= PROXY_WORKER_IN_ERROR;            break;        }        else if (access_status == HTTP_SERVICE_UNAVAILABLE) {            /* Recoverable server error.             * We can failover to another worker             * Mark the worker as unusable if member of load balancer             */            if (balancer) {                worker->s->status |= PROXY_WORKER_IN_ERROR;            }        }        else {            /* Unrecoverable error.             * Return the origin status code to the client.             */            break;        }        /* Try again if the worker is unusable and the service is         * unavailable.         */    } while (!PROXY_WORKER_IS_USABLE(worker) &&             max_attempts > attempts++);    if (DECLINED == access_status) {        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, r->server,                    "proxy: No protocol handler was valid for the URL %s. "                    "If you are using a DSO version of mod_proxy, make sure "                    "the proxy submodules are included in the configuration "                    "using LoadModule.", r->uri);        access_status = HTTP_FORBIDDEN;        goto cleanup;    }cleanup:    if (balancer) {        int post_status = proxy_run_post_request(worker, balancer, r, conf);        if (post_status == DECLINED) {            post_status = OK; /* no post_request handler available */            /* TODO: recycle direct worker */        }    }    proxy_run_request_status(&access_status, r);    return access_status;}/* -------------------------------------------------------------- *//* Setup configurable data */static void * create_proxy_config(apr_pool_t *p, server_rec *s){    proxy_server_conf *ps = apr_pcalloc(p, sizeof(proxy_server_conf));    ps->sec_proxy = apr_array_make(p, 10, sizeof(ap_conf_vector_t *));    ps->proxies = apr_array_make(p, 10, sizeof(struct proxy_remote));    ps->aliases = apr_array_make(p, 10, sizeof(struct proxy_alias));    ps->noproxies = apr_array_make(p, 10, sizeof(struct noproxy_entry));    ps->dirconn = apr_array_make(p, 10, sizeof(struct dirconn_entry));    ps->allowed_connect_ports = apr_array_make(p, 10, sizeof(int));    ps->workers = apr_array_make(p, 10, sizeof(proxy_worker));    ps->balancers = apr_array_make(p, 10, sizeof(proxy_balancer));    ps->forward = NULL;    ps->reverse = NULL;    ps->domain = NULL;    ps->viaopt = via_off; /* initially backward compatible with 1.3.1 */    ps->viaopt_set = 0; /* 0 means default */    ps->req = 0;    ps->req_set = 0;    ps->recv_buffer_size = 0; /* this default was left unset for some reason */    ps->recv_buffer_size_set = 0;    ps->io_buffer_size = AP_IOBUFSIZE;    ps->io_buffer_size_set = 0;    ps->maxfwd = DEFAULT_MAX_FORWARDS;    ps->maxfwd_set = 0;    ps->error_override = 0;    ps->error_override_set = 0;    ps->preserve_host_set = 0;    ps->preserve_host = 0;    ps->timeout = 0;    ps->timeout_set = 0;    ps->badopt = bad_error;    ps->badopt_set = 0;    ps->pool = p;    return ps;}static void * merge_proxy_config(apr_pool_t *p, void *basev, void *overridesv){    proxy_server_conf *ps = apr_pcalloc(p, sizeof(proxy_server_conf));    proxy_server_conf *base = (proxy_server_conf *) basev;    proxy_server_conf *overrides = (proxy_server_conf *) overridesv;    ps->proxies = apr_array_append(p, base->proxies, overrides->proxies);    ps->sec_proxy = apr_array_append(p, base->sec_proxy, overrides->sec_proxy);    ps->aliases = apr_array_append(p, base->aliases, overrides->aliases);    ps->noproxies = apr_array_append(p, base->noproxies, overrides->noproxies);    ps->dirconn = apr_array_append(p, base->dirconn, overrides->dirconn);    ps->allowed_connect_ports = apr_array_append(p, base->allowed_connect_ports, overrides->allowed_connect_ports);    ps->workers = apr_array_append(p, base->workers, overrides->workers);    ps->balancers = apr_array_append(p, base->balancers, overrides->balancers);    ps->forward = overrides->forward ? overrides->forward : base->forward;    ps->reverse = overrides->reverse ? overrides->reverse : base->reverse;    ps->domain = (overrides->domain == NULL) ? base->domain : overrides->domain;    ps->viaopt = (overrides->viaopt_set == 0) ? base->viaopt : overrides->viaopt;    ps->req = (overrides->req_set == 0) ? base->req : overrides->req;    ps->recv_buffer_size = (overrides->recv_buffer_size_set == 0) ? base->recv_buffer_size : overrides->recv_buffer_size;    ps->io_buffer_size = (overrides->io_buffer_size_set == 0) ? base->io_buffer_size : overrides->io_buffer_size;    ps->maxfwd = (overrides->maxfwd_set == 0) ? base->maxfwd : overrides->maxfwd;    ps->error_override = (overrides->error_override_set == 0) ? base->error_override : overrides->error_override;    ps->preserve_host = (overrides->preserve_host_set == 0) ? base->preserve_host : overrides->preserve_host;    ps->timeout= (overrides->timeout_set == 0) ? base->timeout : overrides->timeout;    ps->badopt = (overrides->badopt_set == 0) ? base->badopt : overrides->badopt;    ps->proxy_status = (overrides->proxy_status_set == 0) ? base->proxy_status : overrides->proxy_status;    ps->pool = p;    return ps;}static void *create_proxy_dir_config(apr_pool_t *p, char *dummy){    proxy_dir_conf *new =        (proxy_dir_conf *) apr_pcalloc(p, sizeof(proxy_dir_conf));    /* Filled in by proxysection, when applicable */    /* Put these in the dir config so they work inside <Location> */    new->raliases = apr_array_make(p, 10, sizeof(struct proxy_alias));    new->cookie_paths = apr_array_make(p, 10, sizeof(struct proxy_alias));    new->cookie_domains = apr_array_make(p, 10, sizeof(struct proxy_alias));    new->cookie_path_str = apr_strmatch_precompile(p, "path=", 0);    new->cookie_domain_str = apr_strmatch_precompile(p, "domain=", 0);    return (void *) new;}static void *merge_proxy_dir_config(apr_pool_t *p, void *basev, void *addv){    proxy_dir_conf *new = (proxy_dir_conf *) apr_pcalloc(p, sizeof(proxy_dir_conf));    proxy_dir_conf *add = (proxy_dir_conf *) addv;    proxy_dir_conf *base = (proxy_dir_conf *) basev;    new->p = add->p;    new->p_is_fnmatch = add->p_is_fnmatch;    new->r = add->r;    /* Put these in the dir config so they work inside <Location> */    new->raliases = apr_array_append(p, base->raliases, add->raliases);    new->cookie_paths        = apr_array_append(p, base->cookie_paths, add->cookie_paths);    new->cookie_domains        = apr_array_append(p, base->cookie_domains, add->cookie_domains);    new->cookie_path_str = base->cookie_path_str;    new->cookie_domain_str = base->cookie_domain_str;    return new;}static const char *    add_proxy(cmd_parms *cmd, void *dummy, const char *f1, const char *r1, int regex){    server_rec *s = cmd->server;    proxy_server_conf *conf =    (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module);    struct proxy_remote *new;    char *p, *q;    char *r, *f, *scheme;    ap_regex_t *reg = NULL;    int port;    r = apr_pstrdup(cmd->pool, r1);    scheme = apr_pstrdup(cmd->pool, r1);    f = apr_pstrdup(cmd->pool, f1);    p = strchr(r, ':');    if (p == NULL || p[1] != '/' || p[2] != '/' || p[3] == '\0') {        if (regex)            return "ProxyRemoteMatch: Bad syntax for a remote proxy server";        else            return "ProxyRemote: Bad syntax for a remote proxy server";    }    else {        scheme[p-r] = 0;    }    q = strchr(p + 3, ':');    if (q != NULL) {        if (sscanf(q + 1, "%u", &port) != 1 || port > 65535) {            if (regex)                return "ProxyRemoteMatch: Bad syntax for a remote proxy server (bad port number)";            else                return "ProxyRemote: Bad syntax for a remote proxy server (bad port number)";        }        *q = '\0';    }    else        port = -1;    *p = '\0';    if (regex) {        reg = ap_pregcomp(cmd->pool, f, AP_REG_EXTENDED);        if (!reg)            return "Regular expression for ProxyRemoteMatch could not be compiled.";    }    else        if (strchr(f, ':') == NULL)            ap_str_tolower(f);      /* lowercase scheme */    ap_str_tolower(p + 3);      /* lowercase hostname */    if (port == -1) {        port = apr_uri_port_of_scheme(scheme);    }    new = apr_array_push(conf->proxies);    new->scheme = f;    new->protocol = r;    new->hostname = p + 3;    new->port = port;    new->regexp = reg;    new->use_regex = regex;    return NULL;}static const char *    add_proxy_noregex(cmd_parms *cmd, void *dummy, const char *f1, const char *r1){    return add_proxy(cmd, dummy, f1, r1, 0);}static const char *    add_proxy_regex(cmd_parms *cmd, void *dummy, const char *f1, const char *r1){    return add_proxy(cmd, dummy, f1, r1, 1);}static const char *    add_pass(cmd_parms *cmd, void *dummy, const char *arg){    server_rec *s = cmd->server;    proxy_server_conf *conf =    (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module);    struct proxy_alias *new;    char *f = cmd->path;    char *r = NULL;    char *word;    apr_table_t *params = apr_table_make(cmd->pool, 5);    const apr_array_header_t *arr;    const apr_table_entry_t *elts;    int i;    while (*arg) {        word = ap_getword_conf(cmd->pool, &arg);        if (!f)            f = word;        else if (!r)            r = word;        else {            char *val = strchr(word, '=');            if (!val) {                if (cmd->path)                    return "Invalid ProxyPass parameter.  Parameter must be "                           "in the form 'key=value'";                else                    return "ProxyPass can not have a path when defined in a location";            }            else                *val++ = '\0';            apr_table_setn(params, word, val);        }    };    if (r == NULL)        return "ProxyPass needs a path when not defined in a location";    new = apr_array_push(conf->aliases);    new->fake = apr_pstrdup(cmd->pool, f);    new->real = apr_pstrdup(cmd->pool, r);    if (r[0] == '!' && r[1] == '\0')        return NULL;    arr = apr_table_elts(params);    elts = (const apr_table_entry_t *)arr->elts;    /* Distinguish the balancer from woker */    if (strncasecmp(r, "balancer:", 9) == 0) {        proxy_balancer *balancer = ap_proxy_get_balancer(cmd->pool, conf, r);        if (!balancer) {            const char *err = ap_proxy_add_balancer(&balancer,                                                    cmd->pool,                                                    conf, r);            if (err)                return apr_pstrcat(cmd->temp_pool, "ProxyPass ", err, NULL);        }        for (i = 0; i < arr->nelts; i++) {            const char *err = set_balancer_param(conf, cmd->pool, balancer, elts[i].key,                                                 elts[i].val);            if (err)                return apr_pstrcat(cmd->temp_pool, "ProxyPass ", err, NULL);        }    }    else {        proxy_worker *worker = ap_proxy_get_worker(cmd->temp_pool, conf, r);        if (!worker) {            const char *err = ap_proxy_add_worker(&worker, cmd->pool, conf, r);            if (err)                return apr_pstrcat(cmd->temp_pool, "ProxyPass ", err, NULL);        }        PROXY_COPY_CONF_PARAMS(worker, conf);        for (i = 0; i < arr->nelts; i++) {            const char *err = set_worker_param(cmd->pool, worker, elts[i].key,                                               elts[i].val);            if (err)                return apr_pstrcat(cmd->temp_pool, "ProxyPass ", err, NULL);        }    }    return NULL;}static const char *    add_pass_reverse(cmd_parms *cmd, void *dconf, const char *f, const char *r){    proxy_dir_conf *conf = dconf;    struct proxy_alias *new;    if (r!=NULL && cmd->path == NULL ) {        new = apr_array_push(conf->raliases);        new->fake = f;        new->real = r;    } else if (r==NULL && cmd->path != NULL) {        new = apr_array_push(conf->raliases);        new->fake = cmd->path;        new->real = f;    } else {        if ( r == NULL)            return "ProxyPassReverse needs a path when not defined in a location";        else            return "ProxyPassReverse can not have a path when defined in a location";    }    return NULL;}static const char*    cookie_path(cmd_parms *cmd, void *dconf, const char *f, const char *r){    proxy_dir_conf *conf = dconf;    struct proxy_alias *new;    new = apr_array_push(conf->cookie_paths);    new->fake = f;    new->real = r;    return NULL;}

⌨️ 快捷键说明

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