There is a feature I have wanted in Apache for a little while now: the
ability to preserve the host header when using mod_proxy. This is
mostly useful for two (or more) tier systems, where it is desirable to
pass certain virtual server requests through to backend servers.
The attached patch adds an option:
ProxyPreserveHostHeader On|Off
This option, when set, causes the Host: header of the proxy request to
be passed on intact (including port number) to the backend server. I
know there are other ways of jiggering this, but none I have found are
quite as neat. My primary goal in implementing this is to leave the
front end server configuration untouched (with a wildcard dns entry
pointed at it) and have unmatched virtual hosts passed through to a
backend server on a different host/port. The servers running on this
backend server change with time.
Regards,
Matt
--
Matt Kern
http://www.undue.org/
diff -ur proxy/mod_proxy.c proxy/mod_proxy.c
--- proxy/mod_proxy.c Thu May 30 17:11:32 2002
+++ proxy/mod_proxy.c Thu May 30 17:54:01 2002
@@ -436,6 +436,8 @@
ps->viaopt_set = 0; /* 0 means default */
ps->req = 0;
ps->req_set = 0;
+ ps->hheader = 0;
+ ps->hheader_set = 0;
ps->recv_buffer_size = 0; /* this default was left unset for some
* reason */
ps->recv_buffer_size_set = 0;
@@ -483,6 +485,7 @@
ps->domain = (overrides->domain == NULL) ? base->domain : overrides->domain;
ps->viaopt = (overrides->viaopt_set == 0) ? base->viaopt : overrides->viaopt;
ps->req = (overrides->req_set == 0) ? base->req : overrides->req;
+ ps->hheader = (overrides->hheader_set == 0) ? base->hheader : overrides->hheader;
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;
@@ -703,6 +706,19 @@
static const char *
+ set_proxy_preserve_host_header(cmd_parms *parms, void *dummy, int flag)
+{
+ proxy_server_conf *psf =
+ ap_get_module_config(parms->server->module_config, &proxy_module);
+
+ psf->hheader = flag;
+ psf->hheader_set = 1;
+
+ return NULL;
+}
+
+
+static const char *
set_cache_size(cmd_parms *parms, char *struct_ptr, char *arg)
{
proxy_server_conf *psf =
@@ -936,6 +952,8 @@
"a virtual path and a URL"},
{"ProxyPassReverse", add_pass_reverse, NULL, RSRC_CONF, TAKE2,
"a virtual path and a URL for reverse proxy behaviour"},
+ {"ProxyPreserveHostHeader", set_proxy_preserve_host_header, NULL, RSRC_CONF, FLAG,
+ "on if the original Host: header should be preserved"},
{"ProxyBlock", set_proxy_exclude, NULL, RSRC_CONF, ITERATE,
"A list of names, hosts or domains to which the proxy will not connect"},
{"ProxyReceiveBufferSize", set_recv_buffer_size, NULL, RSRC_CONF, TAKE1,
diff -ur proxy/mod_proxy.h proxy/mod_proxy.h
--- proxy/mod_proxy.h Thu May 30 17:11:32 2002
+++ proxy/mod_proxy.h Thu May 30 17:52:48 2002
@@ -192,6 +192,8 @@
char *domain; /* domain name to use in absence of a domain name in
the request */
int req; /* true if proxy requests are enabled */
char req_set;
+ int hheader; /* true if we want to preserve the host header */
+ char hheader_set;
enum {
via_off,
via_on,
diff -ur proxy/proxy_http.c proxy/proxy_http.c
--- proxy/proxy_http.c Thu May 30 17:11:32 2002
+++ proxy/proxy_http.c Thu May 30 18:38:03 2002
@@ -177,6 +177,7 @@
struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts;
struct nocache_entry *ncent = (struct nocache_entry *) conf->nocaches->elts;
int nocache = 0;
+ int incoming_port = htons ((unsigned short)r->connection->local_addr.sin_port);
if (conf->cache.root == NULL)
nocache = 1;
@@ -312,10 +313,20 @@
ap_bvputs(f, r->method, " ", proxyhost ? url : urlptr, " HTTP/1.1" CRLF,
NULL);
/* Send Host: now, adding it to req_hdrs wouldn't be much better */
- if (destportstr != NULL && destport != DEFAULT_HTTP_PORT)
+ if (conf->hheader) {
+ i = ap_get_server_port(r);
+ if (ap_is_default_port(i, r))
+ strcpy(portstr, "");
+ else
+ ap_snprintf (portstr, sizeof portstr, ":%d", i);
+ ap_bvputs(f, "Host: ", r->hostname, portstr, CRLF, NULL);
+ }
+ else {
+ if (destportstr != NULL && destport != DEFAULT_HTTP_PORT)
ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL);
- else
+ else
ap_bvputs(f, "Host: ", desthost, CRLF, NULL);
+ }
if (conf->viaopt == via_block) {
/* Block all outgoing Via: headers */