Skip to content

Commit

Permalink
*) mod_proxy_http2: fix X-Forward-Host header to carry the correct…
Browse files Browse the repository at this point in the history
… value.

     Fixed PR66752.



git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1912180 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
icing committed Sep 8, 2023
1 parent 18b8e6c commit a2dabc2
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 23 deletions.
4 changes: 4 additions & 0 deletions changes-entries/h2_proxy_forwarded_host.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*) mod_proxy_http2: fix `X-Forward-Host` header to carry the correct value.
Fixed PR66752.
[Stefan Eissing]

20 changes: 10 additions & 10 deletions modules/http2/h2_proxy_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -818,7 +818,7 @@ static apr_status_t open_stream(h2_proxy_session *session, const char *url,
{
h2_proxy_stream *stream;
apr_uri_t puri;
const char *authority, *scheme, *path;
const char *authority, *scheme, *path, *orig_host;
apr_status_t status;
proxy_dir_conf *dconf;

Expand All @@ -842,13 +842,14 @@ static apr_status_t open_stream(h2_proxy_session *session, const char *url,
return status;

scheme = (strcmp(puri.scheme, "h2")? "http" : "https");

orig_host = apr_table_get(r->headers_in, "Host");
if (orig_host == NULL) {
orig_host = r->hostname;
}

dconf = ap_get_module_config(r->per_dir_config, &proxy_module);
if (dconf->preserve_host) {
authority = apr_table_get(r->headers_in, "Host");
if (authority == NULL) {
authority = r->hostname;
}
authority = orig_host;
}
else {
authority = puri.hostname;
Expand Down Expand Up @@ -878,8 +879,6 @@ static apr_status_t open_stream(h2_proxy_session *session, const char *url,

if (dconf->add_forwarded_headers) {
if (PROXYREQ_REVERSE == r->proxyreq) {
const char *buf;

/* Add X-Forwarded-For: so that the upstream has a chance to
* determine, where the original request came from.
*/
Expand All @@ -889,8 +888,9 @@ static apr_status_t open_stream(h2_proxy_session *session, const char *url,
/* Add X-Forwarded-Host: so that upstream knows what the
* original request hostname was.
*/
if ((buf = apr_table_get(r->headers_in, "Host"))) {
apr_table_mergen(stream->req->headers, "X-Forwarded-Host", buf);
if (orig_host) {
apr_table_mergen(stream->req->headers, "X-Forwarded-Host",
orig_host);
}

/* Add X-Forwarded-Server: so that upstream knows what the
Expand Down
31 changes: 18 additions & 13 deletions test/modules/http2/htdocs/cgi/hello.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
#!/usr/bin/env python3

import os
import json

resp = {
'https': os.getenv('HTTPS', ''),
'host': os.getenv('X_HOST', '') if 'X_HOST' in os.environ else os.getenv('SERVER_NAME', ''),
'server': os.getenv('SERVER_NAME', ''),
'h2_original_host': os.getenv('H2_ORIGINAL_HOST', ''),
'port': os.getenv('SERVER_PORT', ''),
'protocol': os.getenv('SERVER_PROTOCOL', ''),
'ssl_protocol': os.getenv('SSL_PROTOCOL', ''),
'h2': os.getenv('HTTP2', ''),
'h2push': os.getenv('H2PUSH', ''),
'h2_stream_id': os.getenv('H2_STREAM_ID', ''),
'x-forwarded-for': os.getenv('HTTP_X_FORWARDED_FOR', ''),
'x-forwarded-host': os.getenv('HTTP_X_FORWARDED_HOST', ''),
'x-forwarded-server': os.getenv('HTTP_X_FORWARDED_SERVER', ''),
}

print("Content-Type: application/json")
print()
print("{")
print(" \"https\" : \"%s\"," % (os.getenv('HTTPS', '')))
print(" \"host\" : \"%s\"," % (os.getenv('X_HOST', '') \
if 'X_HOST' in os.environ else os.getenv('SERVER_NAME', '')))
print(" \"server\" : \"%s\"," % (os.getenv('SERVER_NAME', '')))
print(" \"h2_original_host\" : \"%s\"," % (os.getenv('H2_ORIGINAL_HOST', '')))
print(" \"port\" : \"%s\"," % (os.getenv('SERVER_PORT', '')))
print(" \"protocol\" : \"%s\"," % (os.getenv('SERVER_PROTOCOL', '')))
print(" \"ssl_protocol\" : \"%s\"," % (os.getenv('SSL_PROTOCOL', '')))
print(" \"h2\" : \"%s\"," % (os.getenv('HTTP2', '')))
print(" \"h2push\" : \"%s\"," % (os.getenv('H2PUSH', '')))
print(" \"h2_stream_id\" : \"%s\"" % (os.getenv('H2_STREAM_ID', '')))
print("}")
print(json.JSONEncoder(indent=2).encode(resp))

22 changes: 22 additions & 0 deletions test/modules/http2/test_600_h2proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,28 @@ def test_h2_600_05(self, env, enable_reuse):
else env.http_port2
assert int(r.json[1]["port"]) == exp_port

# test X-Forwarded-* headers
def test_h2_600_06(self, env):
conf = H2Conf(env, extras={
f'cgi.{env.http_tld}': [
"SetEnvIf Host (.+) X_HOST=$1",
f"ProxyPreserveHost on",
f"ProxyPass /h2c/ h2c://127.0.0.1:{env.http_port}/",
f"ProxyPass /h1c/ http://127.0.0.1:{env.http_port}/",
]
})
conf.add_vhost_cgi(proxy_self=True)
conf.install()
assert env.apache_restart() == 0
url = env.mkurl("https", "cgi", "/h1c/hello.py")
r1 = env.curl_get(url, 5)
assert r1.response["status"] == 200
url = env.mkurl("https", "cgi", "/h2c/hello.py")
r2 = env.curl_get(url, 5)
assert r2.response["status"] == 200
for key in ['x-forwarded-for', 'x-forwarded-host','x-forwarded-server']:
assert r1.json[key] == r2.json[key], f'{key} differs proxy_http != proxy_http2'

# lets do some error tests
def test_h2_600_30(self, env):
conf = H2Conf(env)
Expand Down

0 comments on commit a2dabc2

Please sign in to comment.