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 + -
显示快捷键?