mod_proxy.c revision 9df9016759ec9327e256d7fff1af56ddfadb721c
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias/* Licensed to the Apache Software Foundation (ASF) under one or more
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias * contributor license agreements. See the NOTICE file distributed with
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias * this work for additional information regarding copyright ownership.
e21e5f0fa66bf80e14cfd3f571e09b3952e46ad9Alexis Tsogias * The ASF licenses this file to You under the Apache License, Version 2.0
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias * (the "License"); you may not use this file except in compliance with
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias * the License. You may obtain a copy of the License at
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias * Unless required by applicable law or agreed to in writing, software
e21e5f0fa66bf80e14cfd3f571e09b3952e46ad9Alexis Tsogias * distributed under the License is distributed on an "AS IS" BASIS,
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias * See the License for the specific language governing permissions and
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias * limitations under the License.
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis TsogiasAPR_DECLARE_OPTIONAL_FN(int, ssl_proxy_enable, (conn_rec *));
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis TsogiasAPR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis TsogiasAPR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec *));
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis TsogiasAPR_DECLARE_OPTIONAL_FN(char *, ssl_var_lookup,
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias#define MAX(x,y) ((x) >= (y) ? (x) : (y))
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias * A Web proxy module. Stages:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * translate_name: set filename to proxy:<URL>
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * map_to_storage: run proxy_walk (rather than directory_walk/file_walk)
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * can't trust directory_walk/file_walk since these are
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * not in our filesystem. Prevents mod_http from serving
748e10233de9e76b68be4f0050c7b4a7f3c415eaAlexis Tsogias * the TRACE request we will set aside to handle later.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * type_checker: set type to PROXY_MAGIC_TYPE if filename begins proxy:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * fix_ups: convert the URL stored in the filename to the
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias * canonical form.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * handler: handle proxy requests
e21e5f0fa66bf80e14cfd3f571e09b3952e46ad9Alexis Tsogias/* -------------------------------------------------------------- */
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias/* Translate the URL into a 'filename' */
e21e5f0fa66bf80e14cfd3f571e09b3952e46ad9Alexis Tsogias (w)->recv_buffer_size = (c)->recv_buffer_size; \
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias (w)->recv_buffer_size_set = (c)->recv_buffer_size_set; \
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias (w)->io_buffer_size_set = (c)->io_buffer_size_set; \
e21e5f0fa66bf80e14cfd3f571e09b3952e46ad9Alexis Tsogiasstatic const char *set_worker_param(apr_pool_t *p,
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias /* Normalized load factor. Used with BalancerMamber,
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * it is a number between 1 and 100.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias if (worker->lbfactor < 1 || worker->lbfactor > 100)
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias return "LoadFactor must be number between 1..100";
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias /* If set it will give the retry timeout for the worker
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * The default value is 60 seconds, meaning that if
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * in error state, it will be retried after that timeout.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias return "Retry must be at least one second";
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias /* Time in seconds that will destroy all the connections
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * that exced the smax
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias return "TTL must be at least one second";
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias /* Initial number of connections to remote
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias return "Min must be a positive number";
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias /* Maximum number of connections to remote
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias return "Max must be a positive number";
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias /* XXX: More inteligent naming needed */
4e95ffc23b9c5f0b5980ab6f1cacbe7bd9789851Alexis Tsogias /* Maximum number of connections to remote that
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * will not be destroyed
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias return "Smax must be a positive number";
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias /* Acquire timeout in milliseconds.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * If set this will be the maximum time to
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * wait for a free connection.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias return "Acquire must be at least one mili second";
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias worker->acquire = apr_time_make(0, ival * 1000);
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias /* Connection timeout in seconds.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * Defaults to server timeout.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias return "Timeout must be at least one second";
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias worker->io_buffer_size = ((s > AP_IOBUFSIZE) ? s : AP_IOBUFSIZE);
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias else if (!strcasecmp(key, "receivebuffersize")) {
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias return "ReceiveBufferSize must be >= 512 bytes, or 0 for system default.";
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias return "KeepAlive must be On|Off";
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias /* Worker route.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias if (strlen(val) > PROXY_WORKER_MAX_ROUTE_SIZ)
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias return "Route length must be < 64 characters";
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias /* Worker redirection route.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias if (strlen(val) > PROXY_WORKER_MAX_ROUTE_SIZ)
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias return "Redirect length must be < 64 characters";
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias const char *v;
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias /* Worker status.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias for (v = val; *v; v++) {
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias if (*v == '+') {
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias else if (*v == '-') {
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias return "Unknown status parameter option";
4e95ffc23b9c5f0b5980ab6f1cacbe7bd9789851Alexis Tsogias return "flushpackets must be on|off|auto";
4e95ffc23b9c5f0b5980ab6f1cacbe7bd9789851Alexis Tsogias return "flushwait must be <= 1000, or 0 for system default of 10 millseconds.";
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias worker->flush_wait = ival * 1000; /* change to microseconds */
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias return "unknown Worker parameter";
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogiasstatic const char *set_balancer_param(proxy_server_conf *conf,
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias /* Balancer sticky session name.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * Set to something like JSESSIONID or
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * PHPSESSIONID, etc..,
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias /* If set to 'on' the session will break
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * if the worker is in error state or
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias return "failover must be On|Off";
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias /* Balancer timeout in seconds.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * If set this will be the maximum time to
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * wait for a free worker.
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias * Default is not to wait.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias return "timeout must be at least one second";
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias /* Maximum number of failover attempts before
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias return "maximum number of attempts must be a positive number";
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias provider = ap_lookup_provider(PROXY_LBMETHOD, val, "0");
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias return "unknown lbmethod";
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias return "unknown Balancer parameter";
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogiasstatic int alias_match(const char *uri, const char *alias_fakename)
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias const char *end_fakename = alias_fakename + strlen(alias_fakename);
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias const char *aliasp = alias_fakename, *urip = uri;
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias while (aliasp < end_fakename && urip < end_uri) {
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias /* any number of '/' in the alias matches any number in
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * the supplied URI, but there must be at least one...
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias /* Other characters are compared literally */
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias /* fixup badly encoded stuff (e.g. % as last character) */
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias /* We reach the end of the uri before the end of "alias_fakename"
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * for example uri is "/" and alias_fakename "/examples"
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias if (urip == end_uri && aliasp!=end_fakename) {
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias /* Check last alias path component matched all the way */
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias if (aliasp[-1] != '/' && *urip != '\0' && *urip != '/')
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias /* Return number of characters from URI which matched (may be
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * greater than length of alias, since we may have matched
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * doubled slashes)
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias/* Detect if an absoluteURI should be proxied or not. Note that we
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * have to do this during this phase because later phases are
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * "short-circuiting"... i.e. translate_names will end when the first
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias * module returns OK. So for example, if the request is something like:
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias * GET http://othervhost/cgi-bin/printenv HTTP/1.0
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias * mod_alias will notice the /cgi-bin part and ScriptAlias it and
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * short-circuit the proxy... just because of the ordering in the
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * configuration file.
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias /* Ick... msvc (perhaps others) promotes ternary short results to int */
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias /* but it might be something vhosted */
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias && !strcasecmp(r->parsed_uri.scheme, ap_http_scheme(r))
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias && ap_matches_request_vhost(r, r->parsed_uri.hostname,
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias (apr_port_t)(r->parsed_uri.port_str ? r->parsed_uri.port
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias r->filename = apr_pstrcat(r->pool, "proxy:", r->uri, NULL);
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias /* We need special treatment for CONNECT proxying: it has no scheme part */
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias else if (conf->req && r->method_number == M_CONNECT
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias r->filename = apr_pstrcat(r->pool, "proxy:", r->uri, NULL);
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasstatic const char *proxy_interpolate(request_rec *r, const char *str)
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias /* Interpolate an env str in a configuration string
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * Syntax ${var} --> value_of(var)
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * Method: replace one var, and recurse on remainder of string
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * Nothing clever here, and crap like nested vars may do silly things
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * but we'll at least avoid sending the unwary into a loop
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias /* OK, this is syntax we want to interpolate. Is there such a var ? */
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias var = apr_pstrndup(r->pool, start+2, end-(start+2));
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias firstpart = apr_pstrndup(r->pool, str, (start-str));
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogiasstatic apr_array_header_t *proxy_vars(request_rec *r,
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias apr_array_header_t *ret = apr_array_make(r->pool, hdr->nelts,
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias sizeof (struct proxy_alias));
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias struct proxy_alias *old = (struct proxy_alias *) hdr->elts;
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias struct proxy_alias *newcopy = apr_array_push(ret);
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias newcopy->fake = proxy_interpolate(r, old[i].fake);
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias newcopy->real = proxy_interpolate(r, old[i].real);
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias struct proxy_alias *ent = (struct proxy_alias *) conf->aliases->elts;
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias proxy_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias /* someone has already set up the proxy, it was possibly ourselves
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias * in proxy_detect
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias /* XXX: since r->uri has been manipulated already we're not really
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias * compliant with RFC1945 at this point. But this probably isn't
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias * an issue because this is a hybrid proxy/origin server.
1e622ddf5a057555db1924ddc88475c695c6f7f2Alexis Tsogias r->filename = apr_pstrcat(r->pool, "proxy:", real,
return OK;
return DECLINED;
&proxy_module);
for (j = 0; j < num_sec; ++j)
if (entry_proxy->r
return OK;
int access_status;
return DECLINED;
return access_status;
return OK;
char *url, *p;
int access_status;
&proxy_module);
return DECLINED;
return access_status;
return HTTP_BAD_REQUEST;
char *nuri;
const char *ref;
return DECLINED;
&r->parsed_uri,
return HTTP_MOVED_PERMANENTLY;
const char *p2;
int direct_connect = 0;
const char *str;
long maxfwd;
return DECLINED;
switch (r->method_number) {
case M_TRACE: {
int access_status;
return OK;
case M_OPTIONS: {
int access_status;
return OK;
return HTTP_FORBIDDEN;
return HTTP_REQUEST_ENTITY_TOO_LARGE;
if (p == NULL) {
return HTTP_BAD_REQUEST;
return HTTP_MOVED_PERMANENTLY;
!direct_connect; i++) {
#if DEBUGGING
r->uri);
return access_status;
if (!worker)
goto cleanup;
if (!direct_connect) {
goto cleanup;
if (balancer)
if (balancer) {
goto cleanup;
if (balancer) {
return access_status;
return ps;
ps->allowed_connect_ports = apr_array_append(p, base->allowed_connect_ports, overrides->allowed_connect_ports);
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->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->proxy_status = (overrides->proxy_status_set == 0) ? base->proxy_status : overrides->proxy_status;
return ps;
return (void *) new;
return new;
char *r, *f, *scheme;
int port;
if (regex)
scheme[p-r] = 0;
if (q != NULL) {
if (regex)
if (regex) {
if (!reg)
return NULL;
char *r = NULL;
char *word;
while (*arg) {
f = word;
r = word;
if (!val) {
if (r == NULL)
return NULL;
if (!balancer) {
conf, r);
if (err)
if (err)
if (!worker) {
if (err)
if (err)
return NULL;
if ( r == NULL)
return NULL;
return NULL;
return NULL;
int found = 0;
if (!found) {
return NULL;
int *New;
return NULL;
int found = 0;
if (!found) {
#if DEBUGGING
#if DEBUGGING
#if DEBUGGING
#if DEBUGGING
return NULL;
return NULL;
return NULL;
return NULL;
return NULL;
return NULL;
return NULL;
return NULL;
int timeout;
return NULL;
return NULL;
return NULL;
return NULL;
char *word;
while (*arg) {
if (!path)
else if (!name)
if (!val)
if (!path)
if (!name)
if (!worker) {
const char *err;
if (err)
if (!balancer) {
if (err)
return NULL;
const char *err;
if (!balancer) {
if (!worker) {
while (*arg) {
if (!val) {
if (worker)
if (err)
return NULL;
&proxy_module);
const char *errmsg;
return err;
if (!arg) {
return errmsg;
conf->r = r;
return NULL;
{NULL}
if (proxy_ssl_enable) {
if (proxy_ssl_disable) {
return proxy_ssl_disable(c);
if (proxy_is_https) {
return proxy_is_https(c);
const char *var)
if (proxy_ssl_val) {
return NULL;
return OK;
return OK;
++worker;
++balancer;
return OK;
worker++;
if (!reverse) {
s = s->next;
proxy_lb_workers = 0;
return OK;
request_rec *r,
request_rec *r,
(request_rec *r), (r),
(status, r),