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