mod_proxy.c
来自「apache服务器源代码(版本号:2.2.2)」· C语言 代码 · 共 1,862 行 · 第 1/5 页
C
1,862 行
/* Copyright 1999-2005 The Apache Software Foundation or its licensors, as * applicable. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#define CORE_PRIVATE#include "mod_proxy.h"#include "mod_core.h"#include "apr_optional.h"#include "scoreboard.h"#include "mod_status.h"#if (MODULE_MAGIC_NUMBER_MAJOR > 20020903)#include "mod_ssl.h"#elseAPR_DECLARE_OPTIONAL_FN(int, ssl_proxy_enable, (conn_rec *));APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));APR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec *));APR_DECLARE_OPTIONAL_FN(char *, ssl_var_lookup, (apr_pool_t *, server_rec *, conn_rec *, request_rec *, char *));#endif#ifndef MAX#define MAX(x,y) ((x) >= (y) ? (x) : (y))#endif/* * A Web proxy module. Stages: * * translate_name: set filename to proxy:<URL> * map_to_storage: run proxy_walk (rather than directory_walk/file_walk) * can't trust directory_walk/file_walk since these are * not in our filesystem. Prevents mod_http from serving * the TRACE request we will set aside to handle later. * type_checker: set type to PROXY_MAGIC_TYPE if filename begins proxy: * fix_ups: convert the URL stored in the filename to the * canonical form. * handler: handle proxy requests *//* -------------------------------------------------------------- *//* Translate the URL into a 'filename' */#define PROXY_COPY_CONF_PARAMS(w, c) \ do { \ (w)->timeout = (c)->timeout; \ (w)->timeout_set = (c)->timeout_set; \ (w)->recv_buffer_size = (c)->recv_buffer_size; \ (w)->recv_buffer_size_set = (c)->recv_buffer_size_set; \ (w)->io_buffer_size = (c)->io_buffer_size; \ (w)->io_buffer_size_set = (c)->io_buffer_size_set; \ } while (0)static const char *set_worker_param(apr_pool_t *p, proxy_worker *worker, const char *key, const char *val){ int ival; if (!strcasecmp(key, "loadfactor")) { /* Normalized load factor. Used with BalancerMamber, * it is a number between 1 and 100. */ worker->lbfactor = atoi(val); if (worker->lbfactor < 1 || worker->lbfactor > 100) return "LoadFactor must be number between 1..100"; } else if (!strcasecmp(key, "retry")) { /* If set it will give the retry timeout for the worker * The default value is 60 seconds, meaning that if * in error state, it will be retried after that timeout. */ ival = atoi(val); if (ival < 1) return "Retry must be at least one second"; worker->retry = apr_time_from_sec(ival); } else if (!strcasecmp(key, "ttl")) { /* Time in seconds that will destroy all the connections * that exced the smax */ ival = atoi(val); if (ival < 1) return "TTL must be at least one second"; worker->ttl = apr_time_from_sec(ival); } else if (!strcasecmp(key, "min")) { /* Initial number of connections to remote */ ival = atoi(val); if (ival < 0) return "Min must be a positive number"; worker->min = ival; } else if (!strcasecmp(key, "max")) { /* Maximum number of connections to remote */ ival = atoi(val); if (ival < 0) return "Max must be a positive number"; worker->hmax = ival; } /* XXX: More inteligent naming needed */ else if (!strcasecmp(key, "smax")) { /* Maximum number of connections to remote that * will not be destroyed */ ival = atoi(val); if (ival < 0) return "Smax must be a positive number"; worker->smax = ival; } else if (!strcasecmp(key, "acquire")) { /* Acquire timeout in milliseconds. * If set this will be the maximum time to * wait for a free connection. */ ival = atoi(val); if (ival < 1) return "Acquire must be at least one mili second"; worker->acquire = apr_time_make(0, ival * 1000); worker->acquire_set = 1; } else if (!strcasecmp(key, "timeout")) { /* Connection timeout in seconds. * Defaults to server timeout. */ ival = atoi(val); if (ival < 1) return "Timeout must be at least one second"; worker->timeout = apr_time_from_sec(ival); worker->timeout_set = 1; } else if (!strcasecmp(key, "iobuffersize")) { long s = atol(val); worker->io_buffer_size = ((s > AP_IOBUFSIZE) ? s : AP_IOBUFSIZE); worker->io_buffer_size_set = 1; } else if (!strcasecmp(key, "receivebuffersize")) { ival = atoi(val); if (ival < 512 && ival != 0) { return "ReceiveBufferSize must be >= 512 bytes, or 0 for system default."; } worker->recv_buffer_size = ival; worker->recv_buffer_size_set = 1; } else if (!strcasecmp(key, "keepalive")) { if (!strcasecmp(val, "on")) worker->keepalive = 1; else if (!strcasecmp(val, "off")) worker->keepalive = 0; else return "KeepAlive must be On|Off"; worker->keepalive_set = 1; } else if (!strcasecmp(key, "route")) { /* Worker route. */ if (strlen(val) > PROXY_WORKER_MAX_ROUTE_SIZ) return "Route length must be < 64 characters"; worker->route = apr_pstrdup(p, val); } else if (!strcasecmp(key, "redirect")) { /* Worker redirection route. */ if (strlen(val) > PROXY_WORKER_MAX_ROUTE_SIZ) return "Redirect length must be < 64 characters"; worker->redirect = apr_pstrdup(p, val); } else if (!strcasecmp(key, "status")) { const char *v; int mode = 1; /* Worker status. */ for (v = val; *v; v++) { if (*v == '+') { mode = 1; v++; } else if (*v == '-') { mode = 0; v++; } if (*v == 'D' || *v == 'd') { if (mode) worker->status |= PROXY_WORKER_DISABLED; else worker->status &= ~PROXY_WORKER_DISABLED; } else if (*v == 'S' || *v == 's') { if (mode) worker->status |= PROXY_WORKER_STOPPED; else worker->status &= ~PROXY_WORKER_STOPPED; } else if (*v == 'E' || *v == 'e') { if (mode) worker->status |= PROXY_WORKER_IN_ERROR; else worker->status &= ~PROXY_WORKER_IN_ERROR; } else { return "Unknow status parameter option"; } } } else if (!strcasecmp(key, "flushpackets")) { if (!strcasecmp(val, "on")) worker->flush_packets = flush_on; else if (!strcasecmp(val, "off")) worker->flush_packets = flush_off; else if (!strcasecmp(val, "auto")) worker->flush_packets = flush_auto; else return "flushpackets must be on|off|auto"; } else if (!strcasecmp(key, "flushwait")) { ival = atoi(val); if (ival > 1000 || ival < 0) { return "flushwait must be <= 1000, or 0 for system default of 10 millseconds."; } if (ival == 0) worker->flush_wait = PROXY_FLUSH_WAIT; else worker->flush_wait = ival * 1000; /* change to microseconds */ } else { return "unknown Worker parameter"; } return NULL;}static const char *set_balancer_param(proxy_server_conf *conf, apr_pool_t *p, proxy_balancer *balancer, const char *key, const char *val){ int ival; if (!strcasecmp(key, "stickysession")) { /* Balancer sticky session name. * Set to something like JSESSIONID or * PHPSESSIONID, etc.., */ balancer->sticky = apr_pstrdup(p, val); } else if (!strcasecmp(key, "nofailover")) { /* If set to 'on' the session will break * if the worker is in error state or * disabled. */ if (!strcasecmp(val, "on")) balancer->sticky_force = 1; else if (!strcasecmp(val, "off")) balancer->sticky_force = 0; else return "failover must be On|Off"; } else if (!strcasecmp(key, "timeout")) { /* Balancer timeout in seconds. * If set this will be the maximum time to * wait for a free worker. * Default is not to wait. */ ival = atoi(val); if (ival < 1) return "timeout must be at least one second"; balancer->timeout = apr_time_from_sec(ival); } else if (!strcasecmp(key, "maxattempts")) { /* Maximum number of failover attempts before * giving up. */ ival = atoi(val); if (ival < 0) return "maximum number of attempts must be a positive number"; balancer->max_attempts = ival; balancer->max_attempts_set = 1; } else if (!strcasecmp(key, "lbmethod")) { proxy_balancer_method *provider; provider = ap_lookup_provider(PROXY_LBMETHOD, val, "0"); if (provider) { balancer->lbmethod = provider; return NULL; } return "unknown lbmethod"; } else { return "unknown Balancer parameter"; } 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. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?