mod_proxy.c

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

C
1,862
字号
    server_rec *s = cmd->server;    proxy_server_conf *conf =    (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module);    char *name = NULL;    char *word, *val;    proxy_balancer *balancer = NULL;    proxy_worker *worker = NULL;    const char *err;    if (cmd->directive->parent &&        strncasecmp(cmd->directive->parent->directive,                    "<Proxy", 6) == 0) {        const char *pargs = cmd->directive->parent->args;        /* Directive inside <Proxy section         * Parent directive arg is the worker/balancer name.         */        name = ap_getword_conf(cmd->temp_pool, &pargs);        if ((word = ap_strchr(name, '>')))            *word = '\0';    }    else {        /* Standard set directive with worker/balancer         * name as first param.         */        name = ap_getword_conf(cmd->temp_pool, &arg);    }    if (strncasecmp(name, "balancer:", 9) == 0) {        balancer = ap_proxy_get_balancer(cmd->pool, conf, name);        if (!balancer) {            return apr_pstrcat(cmd->temp_pool, "ProxySet can not find '",                               name, "' Balancer.", NULL);        }    }    else {        worker = ap_proxy_get_worker(cmd->temp_pool, conf, name);        if (!worker) {            return apr_pstrcat(cmd->temp_pool, "ProxySet can not find '",                               name, "' Worker.", NULL);        }    }    while (*arg) {        word = ap_getword_conf(cmd->pool, &arg);        val = strchr(word, '=');        if (!val) {            return "Invalid ProxySet parameter. Parameter must be "                   "in the form 'key=value'";        }        else            *val++ = '\0';        if (worker)            err = set_worker_param(cmd->pool, worker, word, val);        else            err = set_balancer_param(conf, cmd->pool, balancer, word, val);        if (err)            return apr_pstrcat(cmd->temp_pool, "ProxySet: ", err, " ", word, "=", val, "; ", name, NULL);    }    return NULL;}static void ap_add_per_proxy_conf(server_rec *s, ap_conf_vector_t *dir_config){    proxy_server_conf *sconf = ap_get_module_config(s->module_config,                                                    &proxy_module);    void **new_space = (void **)apr_array_push(sconf->sec_proxy);    *new_space = dir_config;}static const char *proxysection(cmd_parms *cmd, void *mconfig, const char *arg){    const char *errmsg;    const char *endp = ap_strrchr_c(arg, '>');    int old_overrides = cmd->override;    char *old_path = cmd->path;    proxy_dir_conf *conf;    ap_conf_vector_t *new_dir_conf = ap_create_per_dir_config(cmd->pool);    ap_regex_t *r = NULL;    const command_rec *thiscmd = cmd->cmd;    const char *err = ap_check_cmd_context(cmd,                                           NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);    if (err != NULL) {        return err;    }    if (endp == NULL) {        return apr_pstrcat(cmd->pool, cmd->cmd->name,                           "> directive missing closing '>'", NULL);    }    arg=apr_pstrndup(cmd->pool, arg, endp-arg);    if (!arg) {        if (thiscmd->cmd_data)            return "<ProxyMatch > block must specify a path";        else            return "<Proxy > block must specify a path";    }    cmd->path = ap_getword_conf(cmd->pool, &arg);    cmd->override = OR_ALL|ACCESS_CONF;    if (!strncasecmp(cmd->path, "proxy:", 6))        cmd->path += 6;    /* XXX Ignore case?  What if we proxy a case-insensitive server?!?     * While we are at it, shouldn't we also canonicalize the entire     * scheme?  See proxy_fixup()     */    if (thiscmd->cmd_data) { /* <ProxyMatch> */        r = ap_pregcomp(cmd->pool, cmd->path, AP_REG_EXTENDED);        if (!r) {            return "Regex could not be compiled";        }    }    else if (!strcmp(cmd->path, "~")) {        cmd->path = ap_getword_conf(cmd->pool, &arg);        if (!cmd->path)            return "<Proxy ~ > block must specify a path";        if (strncasecmp(cmd->path, "proxy:", 6))            cmd->path += 6;        r = ap_pregcomp(cmd->pool, cmd->path, AP_REG_EXTENDED);        if (!r) {            return "Regex could not be compiled";        }    }    /* initialize our config and fetch it */    conf = ap_set_config_vectors(cmd->server, new_dir_conf, cmd->path,                                 &proxy_module, cmd->pool);    errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_dir_conf);    if (errmsg != NULL)        return errmsg;    conf->r = r;    conf->p = cmd->path;    conf->p_is_fnmatch = apr_fnmatch_test(conf->p);    ap_add_per_proxy_conf(cmd->server, new_dir_conf);    if (*arg != '\0') {        return apr_pstrcat(cmd->pool, "Multiple ", thiscmd->name,                           "> arguments not (yet) supported.", NULL);    }    cmd->path = old_path;    cmd->override = old_overrides;    return NULL;}static const command_rec proxy_cmds[] ={    AP_INIT_RAW_ARGS("<Proxy", proxysection, NULL, RSRC_CONF,    "Container for directives affecting resources located in the proxied "    "location"),    AP_INIT_RAW_ARGS("<ProxyMatch", proxysection, (void*)1, RSRC_CONF,    "Container for directives affecting resources located in the proxied "    "location, in regular expression syntax"),    AP_INIT_FLAG("ProxyRequests", set_proxy_req, NULL, RSRC_CONF,     "on if the true proxy requests should be accepted"),    AP_INIT_TAKE2("ProxyRemote", add_proxy_noregex, NULL, RSRC_CONF,     "a scheme, partial URL or '*' and a proxy server"),    AP_INIT_TAKE2("ProxyRemoteMatch", add_proxy_regex, NULL, RSRC_CONF,     "a regex pattern and a proxy server"),    AP_INIT_RAW_ARGS("ProxyPass", add_pass, NULL, RSRC_CONF|ACCESS_CONF,     "a virtual path and a URL"),    AP_INIT_TAKE12("ProxyPassReverse", add_pass_reverse, NULL, RSRC_CONF|ACCESS_CONF,     "a virtual path and a URL for reverse proxy behaviour"),    AP_INIT_TAKE2("ProxyPassReverseCookiePath", cookie_path, NULL,       RSRC_CONF|ACCESS_CONF, "Path rewrite rule for proxying cookies"),    AP_INIT_TAKE2("ProxyPassReverseCookieDomain", cookie_domain, NULL,       RSRC_CONF|ACCESS_CONF, "Domain rewrite rule for proxying cookies"),    AP_INIT_ITERATE("ProxyBlock", set_proxy_exclude, NULL, RSRC_CONF,     "A list of names, hosts or domains to which the proxy will not connect"),    AP_INIT_TAKE1("ProxyReceiveBufferSize", set_recv_buffer_size, NULL, RSRC_CONF,     "Receive buffer size for outgoing HTTP and FTP connections in bytes"),    AP_INIT_TAKE1("ProxyIOBufferSize", set_io_buffer_size, NULL, RSRC_CONF,     "IO buffer size for outgoing HTTP and FTP connections in bytes"),    AP_INIT_TAKE1("ProxyMaxForwards", set_max_forwards, NULL, RSRC_CONF,     "The maximum number of proxies a request may be forwarded through."),    AP_INIT_ITERATE("NoProxy", set_proxy_dirconn, NULL, RSRC_CONF,     "A list of domains, hosts, or subnets to which the proxy will connect directly"),    AP_INIT_TAKE1("ProxyDomain", set_proxy_domain, NULL, RSRC_CONF,     "The default intranet domain name (in absence of a domain in the URL)"),    AP_INIT_ITERATE("AllowCONNECT", set_allowed_ports, NULL, RSRC_CONF,     "A list of ports which CONNECT may connect to"),    AP_INIT_TAKE1("ProxyVia", set_via_opt, NULL, RSRC_CONF,     "Configure Via: proxy header header to one of: on | off | block | full"),    AP_INIT_FLAG("ProxyErrorOverride", set_proxy_error_override, NULL, RSRC_CONF,     "use our error handling pages instead of the servers' we are proxying"),    AP_INIT_FLAG("ProxyPreserveHost", set_preserve_host, NULL, RSRC_CONF,     "on if we should preserve host header while proxying"),    AP_INIT_TAKE1("ProxyTimeout", set_proxy_timeout, NULL, RSRC_CONF,     "Set the timeout (in seconds) for a proxied connection. "     "This overrides the server timeout"),    AP_INIT_TAKE1("ProxyBadHeader", set_bad_opt, NULL, RSRC_CONF,     "How to handle bad header line in response: IsError | Ignore | StartBody"),    AP_INIT_RAW_ARGS("BalancerMember", add_member, NULL, RSRC_CONF|ACCESS_CONF,     "A balancer name and scheme with list of params"),    AP_INIT_TAKE1("ProxyStatus", set_status_opt, NULL, RSRC_CONF,     "Configure Status: proxy status to one of: on | off | full"),    AP_INIT_RAW_ARGS("ProxySet", set_proxy_param, NULL, RSRC_CONF|ACCESS_CONF,     "A balancer or worker name with list of params"),    {NULL}};static APR_OPTIONAL_FN_TYPE(ssl_proxy_enable) *proxy_ssl_enable = NULL;static APR_OPTIONAL_FN_TYPE(ssl_engine_disable) *proxy_ssl_disable = NULL;static APR_OPTIONAL_FN_TYPE(ssl_is_https) *proxy_is_https = NULL;static APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *proxy_ssl_val = NULL;PROXY_DECLARE(int) ap_proxy_ssl_enable(conn_rec *c){    /*     * if c == NULL just check if the optional function was imported     * else run the optional function so ssl filters are inserted     */    if (proxy_ssl_enable) {        return c ? proxy_ssl_enable(c) : 1;    }    return 0;}PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c){    if (proxy_ssl_disable) {        return proxy_ssl_disable(c);    }    return 0;}PROXY_DECLARE(int) ap_proxy_conn_is_https(conn_rec *c){    if (proxy_is_https) {        return proxy_is_https(c);    }    else        return 0;}PROXY_DECLARE(const char *) ap_proxy_ssl_val(apr_pool_t *p, server_rec *s,                                             conn_rec *c, request_rec *r,                                             const char *var){    if (proxy_ssl_val) {        /* XXX Perhaps the casting useless */        return (const char *)proxy_ssl_val(p, s, c, r, (char *)var);    }    else        return NULL;}static int proxy_post_config(apr_pool_t *pconf, apr_pool_t *plog,                             apr_pool_t *ptemp, server_rec *s){    proxy_ssl_enable = APR_RETRIEVE_OPTIONAL_FN(ssl_proxy_enable);    proxy_ssl_disable = APR_RETRIEVE_OPTIONAL_FN(ssl_engine_disable);    proxy_is_https = APR_RETRIEVE_OPTIONAL_FN(ssl_is_https);    proxy_ssl_val = APR_RETRIEVE_OPTIONAL_FN(ssl_var_lookup);    return OK;}/* *  proxy Extension to mod_status */static int proxy_status_hook(request_rec *r, int flags){    int i, n;    void *sconf = r->server->module_config;    proxy_server_conf *conf = (proxy_server_conf *)        ap_get_module_config(sconf, &proxy_module);    proxy_balancer *balancer = NULL;    proxy_worker *worker = NULL;    if (flags & AP_STATUS_SHORT || conf->balancers->nelts == 0 ||        conf->proxy_status == status_off)        return OK;    balancer = (proxy_balancer *)conf->balancers->elts;    for (i = 0; i < conf->balancers->nelts; i++) {        ap_rputs("<hr />\n<h1>Proxy LoadBalancer Status for ", r);        ap_rvputs(r, balancer->name, "</h1>\n\n", NULL);        ap_rputs("\n\n<table border=\"0\"><tr>"                 "<th>SSes</th><th>Timeout</th><th>Method</th>"                 "</tr>\n<tr>", r);        ap_rvputs(r, "<td>", balancer->sticky, NULL);        ap_rprintf(r, "</td><td>%" APR_TIME_T_FMT "</td>",                   apr_time_sec(balancer->timeout));        ap_rprintf(r, "<td>%s</td>\n",                   balancer->lbmethod->name);        ap_rputs("</table>\n", r);        ap_rputs("\n\n<table border=\"0\"><tr>"                 "<th>Sch</th><th>Host</th><th>Stat</th>"                 "<th>Route</th><th>Redir</th>"                 "<th>F</th><th>Acc</th><th>Wr</th><th>Rd</th>"                 "</tr>\n", r);        worker = (proxy_worker *)balancer->workers->elts;        for (n = 0; n < balancer->workers->nelts; n++) {            char fbuf[50];            ap_rvputs(r, "<tr>\n<td>", worker->scheme, "</td>", NULL);            ap_rvputs(r, "<td>", worker->hostname, "</td><td>", NULL);            if (worker->s->status & PROXY_WORKER_DISABLED)                ap_rputs("Dis", r);            else if (worker->s->status & PROXY_WORKER_IN_ERROR)                ap_rputs("Err", r);            else if (worker->s->status & PROXY_WORKER_INITIALIZED)                ap_rputs("Ok", r);            else                ap_rputs("-", r);            ap_rvputs(r, "</td><td>", worker->s->route, NULL);            ap_rvputs(r, "</td><td>", worker->s->redirect, NULL);            ap_rprintf(r, "</td><td>%d</td>", worker->s->lbfactor);            ap_rprintf(r, "<td>%d</td><td>", (int)(worker->s->elected));            ap_rputs(apr_strfsize(worker->s->transferred, fbuf), r);            ap_rputs("</td><td>", r);            ap_rputs(apr_strfsize(worker->s->read, fbuf), r);            ap_rputs("</td>\n", r);            /* TODO: Add the rest of dynamic worker data */            ap_rputs("</tr>\n", r);            ++worker;        }        ap_rputs("</table>\n", r);        ++balancer;    }    ap_rputs("<hr /><table>\n"             "<tr><th>SSes</th><td>Sticky session name</td></tr>\n"             "<tr><th>Timeout</th><td>Balancer Timeout</td></tr>\n"             "<tr><th>Sch</th><td>Connection scheme</td></tr>\n"             "<tr><th>Host</th><td>Backend Hostname</td></tr>\n"             "<tr><th>Stat</th><td>Worker status</td></tr>\n"             "<tr><th>Route</th><td>Session Route</td></tr>\n"             "<tr><th>Redir</th><td>Session Route Redirection</td></tr>\n"             "<tr><th>F</th><td>Load Balancer Factor in %</td></tr>\n"             "<tr><th>Acc</th><td>Number of requests</td></tr>\n"             "<tr><th>Wr</th><td>Number of bytes transferred</td></tr>\n"             "<tr><th>Rd</th><td>Number of bytes read</td></tr>\n"             "</table>", r);    return OK;}static void child_init(apr_pool_t *p, server_rec *s){    proxy_worker *reverse = NULL;    while (s) {        void *sconf = s->module_config;        proxy_server_conf *conf;        proxy_worker *worker;        int i;        conf = (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);        /* Initialize worker's shared scoreboard data */        worker = (proxy_worker *)conf->workers->elts;        for (i = 0; i < conf->workers->nelts; i++) {            ap_proxy_initialize_worker_share(conf, worker, s);            ap_proxy_initial

⌨️ 快捷键说明

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