mod_proxy.c revision 9cb787a8a3d06704ab9c51ffd51525b364151182
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse/* ====================================================================
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * The Apache Software License, Version 1.1
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * Copyright (c) 2000 The Apache Software Foundation. All rights
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * reserved.
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * Redistribution and use in source and binary forms, with or without
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * modification, are permitted provided that the following conditions
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * are met:
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * 1. Redistributions of source code must retain the above copyright
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * notice, this list of conditions and the following disclaimer.
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * 2. Redistributions in binary form must reproduce the above copyright
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * notice, this list of conditions and the following disclaimer in
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * the documentation and/or other materials provided with the
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * distribution.
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * 3. The end-user documentation included with the redistribution,
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * if any, must include the following acknowledgment:
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * "This product includes software developed by the
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * Apache Software Foundation (http://www.apache.org/)."
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * Alternately, this acknowledgment may appear in the software itself,
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * if and wherever such third-party acknowledgments normally appear.
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * 4. The names "Apache" and "Apache Software Foundation" must
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * not be used to endorse or promote products derived from this
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * software without prior written permission. For written
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * permission, please contact apache@apache.org.
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * 5. Products derived from this software may not be called "Apache",
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * nor may "Apache" appear in their name, without prior written
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * permission of the Apache Software Foundation.
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * SUCH DAMAGE.
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * ====================================================================
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * This software consists of voluntary contributions made by many
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * individuals on behalf of the Apache Software Foundation. For more
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * information on the Apache Software Foundation, please see
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * Portions of this software are based upon public domain software
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * originally written at the National Center for Supercomputing Applications,
d86ef5503dcbc38e87c0e03cd3e1f16458cb6323rse * University of Illinois, Urbana-Champaign.
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse/* Some WWW schemes and their default ports; this is basically /etc/services */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse/* This will become global when the protocol abstraction comes */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * A Web proxy module. Stages:
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * translate_name: set filename to proxy:<URL>
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * type_checker: set type to PROXY_MAGIC_TYPE if filename begins proxy:
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * fix_ups: convert the URL stored in the filename to the
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * canonical form.
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * handler: handle proxy requests
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse/* -------------------------------------------------------------- */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse/* Translate the URL into a 'filename' */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrsestatic int alias_match(const char *uri, const char *alias_fakename)
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse const char *end_fakename = alias_fakename + strlen(alias_fakename);
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* any number of '/' in the alias matches any number in
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * the supplied URI, but there must be at least one...
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* Other characters are compared literally */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* Check last alias path component matched all the way */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* Return number of characters from URI which matched (may be
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * greater than length of alias, since we may have matched
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * doubled slashes)
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse/* Detect if an absoluteURI should be proxied or not. Note that we
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * have to do this during this phase because later phases are
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * "short-circuiting"... i.e. translate_names will end when the first
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * module returns OK. So for example, if the request is something like:
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * mod_alias will notice the /cgi-bin part and ScriptAlias it and
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * short-circuit the proxy... just because of the ordering in the
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * configuration file.
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse conf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* but it might be something vhosted */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse r->parsed_uri.port_str ? r->parsed_uri.port : ap_default_port(r)))) {
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse r->filename = ap_pstrcat(r->pool, "proxy:", r->uri, NULL);
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* We need special treatment for CONNECT proxying: it has no scheme part */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse r->filename = ap_pstrcat(r->pool, "proxy:", r->uri, NULL);
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse struct proxy_alias *ent = (struct proxy_alias *) conf->aliases->elts;
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* someone has already set up the proxy, it was possibly ourselves
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * in proxy_detect
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* XXX: since r->uri has been manipulated already we're not really
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * compliant with RFC1945 at this point. But this probably isn't
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * an issue because this is a hybrid proxy/origin server.
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse if (len > 0) {
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse r->filename = ap_pstrcat(r->pool, "proxy:", ent[i].real,
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse/* -------------------------------------------------------------- */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse/* Fixup the filename */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * Canonicalise the URL
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse char *url, *p;
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse if (!r->proxyreq || strncmp(r->filename, "proxy:", 6) != 0)
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse/* canonicalise each specific scheme */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse return ap_proxy_http_canon(r, url + 5, "http", DEFAULT_HTTP_PORT);
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse/* Send a redirection if the request contains a hostname which is not
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * fully qualified, i.e. doesn't have a domain name appended. Some proxy
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * servers like Netscape's allow this and access hosts from the local
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * domain in this case. I think it is better to redirect to a FQDN, since
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * these will later be found in the bookmarks files.
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * The "ProxyDomain" directive determines what domain will be appended
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrsestatic int proxy_needsdomain(request_rec *r, const char *url, const char *domain)
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse const char *ref;
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* We only want to worry about GETs */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse if (!r->proxyreq || r->method_number != M_GET || !r->parsed_uri.hostname)
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* If host does contain a dot already, or it is "localhost", decline */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse || strcasecmp(r->parsed_uri.hostname, "localhost") == 0)
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* Reassemble the request, but insert the domain after the host name */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* Note that the domain name always starts with a dot */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse r->parsed_uri.hostname = ap_pstrcat(r->pool, r->parsed_uri.hostname,
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r,
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse/* -------------------------------------------------------------- */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse/* Invoke handler */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse struct proxy_remote *ents = (struct proxy_remote *) proxies->elts;
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse const char *maxfwd_str;
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse if (!r->proxyreq || strncmp(r->filename, "proxy:", 6) != 0)
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse ap_psprintf(r->pool, "%d", (maxfwd > 0) ? maxfwd-1 : 0));
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)))
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse imstr = ap_table_get(r->headers_in, "If-Modified-Since");
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* can this request be cached at all? */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* now we need to check if the last modified date is write if */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse time_t ims = (time_t)ap_parseHTTPdate(ap_proxy_date_canon(r->pool, imstr));
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* ok we were asked to check, so let's do that */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse return has_m ? HTTP_NOT_MODIFIED : ap_proxy_cache_send(r, cr);
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* if there wasn't an entry in the cache we get here,
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse we need to create one */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* If the host doesn't have a domain name, add one and redirect. */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse *p = '\0';
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* Check URI's destination host against NoProxy hosts */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* Bypass ProxyRemote server lookup if configured as NoProxy */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* we only know how to handle communication to a proxy via http */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /*if (strcasecmp(scheme, "http") == 0) */
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse struct dirconn_entry *list = (struct dirconn_entry *) conf->dirconn->elts;
#if DEBUGGING
r->uri);
if (!direct_connect)
(p != NULL &&
return rc;
return HTTP_FORBIDDEN;
return ps;
int port;
if (q != NULL) {
return NULL;
proxy_server_conf *psf = (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module);
int found = 0;
if (!found) {
return NULL;
return NULL;
&proxy_module);
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;
{NULL}
{NULL}
static void register_hooks(void)