proxy_http.c revision dc341925f8f289b12112314d102139725a917464
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova/* ====================================================================
e9458b1a7a19a63aa4c179f9ab20f4d50681c168Jens Elkner * The Apache Software License, Version 1.1
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * Redistribution and use in source and binary forms, with or without
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * modification, are permitted provided that the following conditions
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova * 1. Redistributions of source code must retain the above copyright
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * notice, this list of conditions and the following disclaimer.
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * 2. Redistributions in binary form must reproduce the above copyright
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova * notice, this list of conditions and the following disclaimer in
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * the documentation and/or other materials provided with the
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * distribution.
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * 3. The end-user documentation included with the redistribution,
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * if any, must include the following acknowledgment:
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova * "This product includes software developed by the
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * Apache Software Foundation (http://www.apache.org/)."
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova * Alternately, this acknowledgment may appear in the software itself,
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * if and wherever such third-party acknowledgments normally appear.
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * 4. The names "Apache" and "Apache Software Foundation" must
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova * not be used to endorse or promote products derived from this
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * software without prior written permission. For written
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova * permission, please contact apache@apache.org.
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova * 5. Products derived from this software may not be called "Apache",
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * nor may "Apache" appear in their name, without prior written
118add2c5ac398465f6f66adb165852dffe1264dKristina Sojakova * permission of the Apache Software Foundation.
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
118add2c5ac398465f6f66adb165852dffe1264dKristina Sojakova * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * SUCH DAMAGE.
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * ====================================================================
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * This software consists of voluntary contributions made by many
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * individuals on behalf of the Apache Software Foundation. For more
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * information on the Apache Software Foundation, please see
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova * Portions of this software are based upon public domain software
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova * originally written at the National Center for Supercomputing Applications,
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova * University of Illinois, Urbana-Champaign.
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova/* HTTP routines for Apache proxy */
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakovamodule AP_MODULE_DECLARE_DATA proxy_http_module;
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakovaint ap_proxy_http_canon(request_rec *r, char *url);
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakovaint ap_proxy_http_handler(request_rec *r, proxy_server_conf *conf,
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova * Canonicalise http-like URLs.
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova * scheme is the scheme for the URL
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova * url is the URL starting with the first '/'
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder * def_port is the default port for this scheme.
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakovaint ap_proxy_http_canon(request_rec *r, char *url)
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova /* ap_default_port_for_scheme() */
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova else if (strncasecmp(url, "https:", 6) == 0) {
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova def_port = apr_uri_default_port_for_scheme(scheme);
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova "proxy: HTTP: canonicalising URL %s", url);
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder /* do syntatic check.
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder * We break the URL into host, port, path, search
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);
3c0bf20712a0f21aaedc0a9a9c8376bc1e90e799Kristina Sojakova /* now parse path/search args, according to rfc1738 */
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder /* N.B. if this isn't a true proxy request, then the URL _path_
3c0bf20712a0f21aaedc0a9a9c8376bc1e90e799Kristina Sojakova * has already been decoded. True proxy requests have r->uri
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova * == r->unparsed_uri, and no others have that property.
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova /* process path */
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, r->proxyreq);
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova apr_snprintf(sport, sizeof(sport), ":%d", port);
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova r->filename = apr_pstrcat(r->pool, "proxy:", scheme, "://", host, sport, "/",
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova path, (search) ? "?" : "", (search) ? search : "", NULL);
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakovastatic const char *ap_proxy_location_reverse_map(request_rec *r, proxy_server_conf *conf, const char *url)
3c0bf20712a0f21aaedc0a9a9c8376bc1e90e799Kristina Sojakova /* XXX FIXME: Make sure this handled the ambiguous case of the :80
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova * after the hostname */
3c0bf20712a0f21aaedc0a9a9c8376bc1e90e799Kristina Sojakova ent = (struct proxy_alias *)conf->raliases->elts;
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova for (i = 0; i < conf->raliases->nelts; i++) {
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova if (l1 >= l2 && strncmp(ent[i].real, url, l2) == 0) {
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder u = apr_pstrcat(r->pool, ent[i].fake, &url[l2], NULL);
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder return ap_construct_url(r->pool, u, r);
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova/* Clear all connection-based headers from the incoming headers table */
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroederstatic void ap_proxy_clear_connection(apr_pool_t *p, apr_table_t *headers)
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder char *next = apr_pstrdup(p, apr_table_get(headers, "Connection"));
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder apr_table_unset(headers, "Proxy-Connection");
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova while (*next && !apr_isspace(*next) && (*next != ','))
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova while (*next && (apr_isspace(*next) || (*next == ','))) {
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder apr_table_unset(headers, "Connection");
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova * This handles http:// URLs, and other URLs using a remote proxy over http
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova * If proxyhost is NULL, then contact the server directly, otherwise
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova * go via the proxy.
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder * Note that if a proxy is used, then URLs other than http: can be accessed,
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder * also, if we have trouble which is clearly specific to the proxy, then
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova * we return DECLINED so that we can try another proxy. (Or the direct
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakovaint ap_proxy_http_handler(request_rec *r, proxy_server_conf *conf,
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova int i, len, backasswards, eos, close=0, failed=0, new=0;
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder apr_array_header_t *headers_in_array;
3c0bf20712a0f21aaedc0a9a9c8376bc1e90e799Kristina Sojakova /* Note: Memory pool allocation.
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder * A downstream keepalive connection is always connected to the existence
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova * (or not) of an upstream keepalive connection. If this is not done then
3c0bf20712a0f21aaedc0a9a9c8376bc1e90e799Kristina Sojakova * load balancing against multiple backend servers breaks (one backend
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova * server ends up taking 100% of the load), and the risk is run of
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova * downstream keepalive connections being kept open unnecessarily. This
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder * keeps webservers busy and ties up resources.
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova * As a result, we allocate all sockets out of the upstream connection
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova * pool, and when we want to reuse a socket, we check first whether the
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova * connection ID of the current upstream connection is the same as that
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova * of the connection when the socket was opened.
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder apr_bucket_brigade *bb = apr_brigade_create(p);
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova /* is it for us? */
3c0bf20712a0f21aaedc0a9a9c8376bc1e90e799Kristina Sojakova ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova return DECLINED; /* only interested in HTTP */
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova /* create space for state information */
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova backend = (proxy_conn_rec *) ap_get_module_config(c->conn_config, &proxy_http_module);
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova backend = ap_pcalloc(c->pool, sizeof(proxy_conn_rec));
err = apr_sockaddr_info_get(&uri_addr, apr_pstrdup(c->pool, uri.hostname), APR_UNSPEC, uri.port, 0, c->pool);
if (proxyname) {
i = ap_get_server_port(r);
if (ap_is_default_port(i,r)) {
new = 0;
if (new) {
return HTTP_INTERNAL_SERVER_ERROR;
while (connect_addr) {
failed = 0;
if (failed) {
if (proxyname) {
return DECLINED;
return HTTP_BAD_GATEWAY;
if (!origin) {
return HTTP_INTERNAL_SERVER_ERROR;
if (close) {
const char *buf;
e = apr_bucket_flush_create();
if (ap_should_client_block(r)) {
e = apr_bucket_flush_create();
backasswards = 0;
const char *buf;
const char *buf;
const char *buf;
if (backasswards) {
const char *buf;
if (close) {
e = apr_bucket_flush_create();
return OK;