mod_proxy.c revision 4a98c07ecf4f27a9b18963bbe85260857664d03b
8a77240a809197c92c0736c431b4b88947a7bac1Christian Maeder/* ====================================================================
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * The Apache Software License, Version 1.1
ece3b1a5353a9af3c966a1d5453594ed35334f7bJonathan von Schroeder * Copyright (c) 2000-2002 The Apache Software Foundation. All rights
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * Redistribution and use in source and binary forms, with or without
98890889ffb2e8f6f722b00e265a211f13b5a861Corneliu-Claudiu Prodescu * modification, are permitted provided that the following conditions
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * 1. Redistributions of source code must retain the above copyright
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * notice, this list of conditions and the following disclaimer.
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * 2. Redistributions in binary form must reproduce the above copyright
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * notice, this list of conditions and the following disclaimer in
6820f0de92751e29d73d64db48e776591f529a76Christian Maeder * the documentation and/or other materials provided with the
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * distribution.
6820f0de92751e29d73d64db48e776591f529a76Christian Maeder * 3. The end-user documentation included with the redistribution,
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * if any, must include the following acknowledgment:
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * "This product includes software developed by the
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * Apache Software Foundation (http://www.apache.org/)."
6820f0de92751e29d73d64db48e776591f529a76Christian Maeder * Alternately, this acknowledgment may appear in the software itself,
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * if and wherever such third-party acknowledgments normally appear.
6820f0de92751e29d73d64db48e776591f529a76Christian Maeder * 4. The names "Apache" and "Apache Software Foundation" must
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * not be used to endorse or promote products derived from this
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * software without prior written permission. For written
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * permission, please contact apache@apache.org.
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * 5. Products derived from this software may not be called "Apache",
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * nor may "Apache" appear in their name, without prior written
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * permission of the Apache Software Foundation.
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder * ====================================================================
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * This software consists of voluntary contributions made by many
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * individuals on behalf of the Apache Software Foundation. For more
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * information on the Apache Software Foundation, please see
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * Portions of this software are based upon public domain software
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * originally written at the National Center for Supercomputing Applications,
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * University of Illinois, Urbana-Champaign.
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroederextern module AP_MODULE_DECLARE_DATA proxy_module;
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder#define MAX(x,y) ((x) >= (y) ? (x) : (y))
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * A Web proxy module. Stages:
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * translate_name: set filename to proxy:<URL>
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * map_to_storage: run proxy_walk (rather than directory_walk/file_walk)
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * can't trust directory_walk/file_walk since these are
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * not in our filesystem. Prevents mod_http from serving
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * the TRACE request we will set aside to handle later.
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * type_checker: set type to PROXY_MAGIC_TYPE if filename begins proxy:
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * fix_ups: convert the URL stored in the filename to the
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * canonical form.
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * handler: handle proxy requests
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder/* -------------------------------------------------------------- */
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder/* Translate the URL into a 'filename' */
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroederstatic int alias_match(const char *uri, const char *alias_fakename)
ece3b1a5353a9af3c966a1d5453594ed35334f7bJonathan von Schroeder const char *end_fakename = alias_fakename + strlen(alias_fakename);
ece3b1a5353a9af3c966a1d5453594ed35334f7bJonathan von Schroeder const char *aliasp = alias_fakename, *urip = uri;
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder /* any number of '/' in the alias matches any number in
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * the supplied URI, but there must be at least one...
d71447e45047d07006b4c20409fbd8ea287df01fJonathan von Schroeder /* Other characters are compared literally */
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder /* Check last alias path component matched all the way */
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder if (aliasp[-1] != '/' && *urip != '\0' && *urip != '/')
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder /* Return number of characters from URI which matched (may be
ece3b1a5353a9af3c966a1d5453594ed35334f7bJonathan von Schroeder * greater than length of alias, since we may have matched
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * doubled slashes)
ece3b1a5353a9af3c966a1d5453594ed35334f7bJonathan von Schroeder/* Detect if an absoluteURI should be proxied or not. Note that we
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * have to do this during this phase because later phases are
ece3b1a5353a9af3c966a1d5453594ed35334f7bJonathan von Schroeder * "short-circuiting"... i.e. translate_names will end when the first
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * module returns OK. So for example, if the request is something like:
ece3b1a5353a9af3c966a1d5453594ed35334f7bJonathan von Schroeder * GET http://othervhost/cgi-bin/printenv HTTP/1.0
ece3b1a5353a9af3c966a1d5453594ed35334f7bJonathan von Schroeder * mod_alias will notice the /cgi-bin part and ScriptAlias it and
ece3b1a5353a9af3c966a1d5453594ed35334f7bJonathan von Schroeder * short-circuit the proxy... just because of the ordering in the
ece3b1a5353a9af3c966a1d5453594ed35334f7bJonathan von Schroeder * configuration file.
ece3b1a5353a9af3c966a1d5453594ed35334f7bJonathan von Schroederstatic int proxy_detect(request_rec *r)
ece3b1a5353a9af3c966a1d5453594ed35334f7bJonathan von Schroeder void *sconf = r->server->module_config;
ece3b1a5353a9af3c966a1d5453594ed35334f7bJonathan von Schroeder conf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder /* Ick... msvc (perhaps others) promotes ternary short results to int */
ece3b1a5353a9af3c966a1d5453594ed35334f7bJonathan von Schroeder if (conf->req && r->parsed_uri.scheme) {
ece3b1a5353a9af3c966a1d5453594ed35334f7bJonathan von Schroeder /* but it might be something vhosted */
d71447e45047d07006b4c20409fbd8ea287df01fJonathan von Schroeder && !strcasecmp(r->parsed_uri.scheme, ap_http_method(r))
ece3b1a5353a9af3c966a1d5453594ed35334f7bJonathan von Schroeder && ap_matches_request_vhost(r, r->parsed_uri.hostname,
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder (apr_port_t)(r->parsed_uri.port_str ? r->parsed_uri.port
d71447e45047d07006b4c20409fbd8ea287df01fJonathan von Schroeder r->filename = apr_pstrcat(r->pool, "proxy:", r->uri, NULL);
ece3b1a5353a9af3c966a1d5453594ed35334f7bJonathan von Schroeder /* We need special treatment for CONNECT proxying: it has no scheme part */
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder else if (conf->req && r->method_number == M_CONNECT
ece3b1a5353a9af3c966a1d5453594ed35334f7bJonathan von Schroeder r->filename = apr_pstrcat(r->pool, "proxy:", r->uri, NULL);
ece3b1a5353a9af3c966a1d5453594ed35334f7bJonathan von Schroederstatic int proxy_trans(request_rec *r)
d71447e45047d07006b4c20409fbd8ea287df01fJonathan von Schroeder void *sconf = r->server->module_config;
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder struct proxy_alias *ent = (struct proxy_alias *) conf->aliases->elts;
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder /* someone has already set up the proxy, it was possibly ourselves
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * in proxy_detect
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder /* XXX: since r->uri has been manipulated already we're not really
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder * compliant with RFC1945 at this point. But this probably isn't
d71447e45047d07006b4c20409fbd8ea287df01fJonathan von Schroeder * an issue because this is a hybrid proxy/origin server.
d71447e45047d07006b4c20409fbd8ea287df01fJonathan von Schroeder for (i = 0; i < conf->aliases->nelts; i++) {
b35e053c2c5a5ea0f13decfd0303894861d82b4dJonathan von Schroeder len = alias_match(r->uri, ent[i].fake);
if (len > 0) {
return DECLINED;
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;
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;
if (p == NULL)
return HTTP_BAD_REQUEST;
return HTTP_MOVED_PERMANENTLY;
int ii;
#if DEBUGGING
r->uri);
if (!direct_connect) {
return access_status;
return HTTP_FORBIDDEN;
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;
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;
if ( r== NULL)
return NULL;
&proxy_module);
if ( r == 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;
&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);
return OK;
(request_rec *r), (r),