diff options
-rw-r--r-- | changes-entries/h2_proxy_host.txt | 4 | ||||
-rw-r--r-- | modules/http2/h2_proxy_session.c | 11 | ||||
-rw-r--r-- | test/modules/http2/htdocs/cgi/hello.py | 1 | ||||
-rw-r--r-- | test/modules/http2/htdocs/cgi/mnot164.py | 9 | ||||
-rw-r--r-- | test/modules/http2/test_100_conn_reuse.py | 2 | ||||
-rw-r--r-- | test/modules/http2/test_600_h2proxy.py | 53 |
6 files changed, 66 insertions, 14 deletions
diff --git a/changes-entries/h2_proxy_host.txt b/changes-entries/h2_proxy_host.txt new file mode 100644 index 0000000000..bbf34d648c --- /dev/null +++ b/changes-entries/h2_proxy_host.txt @@ -0,0 +1,4 @@ + *) mod_proxy_http2: use only the ':authority' header to forward 'Host' + information to a backend. Deduce ':authority' from what the client + sent when 'ProxyPreserveHost' is on. + [Stefan Eissing]
\ No newline at end of file diff --git a/modules/http2/h2_proxy_session.c b/modules/http2/h2_proxy_session.c index dfe3a2c245..36b177b76a 100644 --- a/modules/http2/h2_proxy_session.c +++ b/modules/http2/h2_proxy_session.c @@ -838,7 +838,10 @@ static apr_status_t open_stream(h2_proxy_session *session, const char *url, dconf = ap_get_module_config(r->per_dir_config, &proxy_module); if (dconf->preserve_host) { - authority = r->hostname; + authority = apr_table_get(r->headers_in, "Host"); + if (authority == NULL) { + authority = r->hostname; + } } else { authority = puri.hostname; @@ -847,6 +850,9 @@ static apr_status_t open_stream(h2_proxy_session *session, const char *url, /* port info missing and port is not default for scheme: append */ authority = apr_psprintf(stream->pool, "%s:%d", authority, puri.port); } + ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, session->c, + "authority=%s from uri.hostname=%s and uri.port=%d", + authority, puri.hostname, puri.port); } /* we need this for mapping relative uris in headers ("Link") back @@ -884,7 +890,8 @@ static apr_status_t open_stream(h2_proxy_session *session, const char *url, r->server->server_hostname); } } - + apr_table_unset(r->headers_in, "Host"); + /* Tuck away all already existing cookies */ stream->saves = apr_table_make(r->pool, 2); apr_table_do(add_header, stream->saves, r->headers_out, "Set-Cookie", NULL); diff --git a/test/modules/http2/htdocs/cgi/hello.py b/test/modules/http2/htdocs/cgi/hello.py index 9fb2eb689d..f9aed3f1a4 100644 --- a/test/modules/http2/htdocs/cgi/hello.py +++ b/test/modules/http2/htdocs/cgi/hello.py @@ -6,6 +6,7 @@ print("Content-Type: application/json") print() print("{") print(" \"https\" : \"%s\"," % (os.getenv('HTTPS', ''))) +print(" \"x_host\" : \"%s\"," % (os.getenv('X_HOST', ''))) print(" \"host\" : \"%s\"," % (os.getenv('SERVER_NAME', ''))) print(" \"port\" : \"%s\"," % (os.getenv('SERVER_PORT', ''))) print(" \"protocol\" : \"%s\"," % (os.getenv('SERVER_PROTOCOL', ''))) diff --git a/test/modules/http2/htdocs/cgi/mnot164.py b/test/modules/http2/htdocs/cgi/mnot164.py index 949b0f195b..0e5d107246 100644 --- a/test/modules/http2/htdocs/cgi/mnot164.py +++ b/test/modules/http2/htdocs/cgi/mnot164.py @@ -12,10 +12,13 @@ try: except KeyError: text="a" count=77784 - - + +count = int(count) + print("Status: 200 OK") print("Content-Type: text/html") print() -sys.stdout.write(text*int(count)) +sys.stdout.flush() +for _ in range(count): + sys.stdout.write(text) diff --git a/test/modules/http2/test_100_conn_reuse.py b/test/modules/http2/test_100_conn_reuse.py index e0b663190a..3ebac24d60 100644 --- a/test/modules/http2/test_100_conn_reuse.py +++ b/test/modules/http2/test_100_conn_reuse.py @@ -27,7 +27,7 @@ class TestConnReuse: def test_h2_100_02(self, env): url = env.mkurl("https", "cgi", "/hello.py") hostname = ("cgi-alias.%s" % env.http_tld) - r = env.curl_get(url, 5, options=[ "-H", "Host:%s" % hostname ]) + r = env.curl_get(url, 5, options=["-H", f"Host: {hostname}"]) assert r.response["status"] == 200 assert "HTTP/2" == r.response["protocol"] assert hostname == r.response["json"]["host"] diff --git a/test/modules/http2/test_600_h2proxy.py b/test/modules/http2/test_600_h2proxy.py index d27143d22c..0f368eda03 100644 --- a/test/modules/http2/test_600_h2proxy.py +++ b/test/modules/http2/test_600_h2proxy.py @@ -6,16 +6,15 @@ from .env import H2Conf, H2TestEnv @pytest.mark.skipif(condition=H2TestEnv.is_unsupported, reason="mod_http2 not supported here") class TestH2Proxy: - @pytest.fixture(autouse=True, scope='class') - def _class_scope(self, env): - conf = H2Conf(env) + def test_h2_600_01(self, env): + conf = H2Conf(env, extras={ + f'cgi.{env.http_tld}': [ + "SetEnvIf Host (.+) X_HOST=$1", + ] + }) conf.add_vhost_cgi(h2proxy_self=True) - if env.verbosity > 1: - conf.add("LogLevel proxy:trace2 proxy_http2:trace2") conf.install() assert env.apache_restart() == 0 - - def test_h2_600_01(self, env): url = env.mkurl("https", "cgi", "/h2proxy/hello.py") r = env.curl_get(url, 5) assert r.response["status"] == 200 @@ -24,4 +23,42 @@ class TestH2Proxy: assert r.response["json"]["ssl_protocol"] != "" assert r.response["json"]["h2"] == "on" assert r.response["json"]["h2push"] == "off" - assert r.response["json"]["host"] == f"cgi.{env.http_tld}" + assert r.response["json"]["x_host"] == f"cgi.{env.http_tld}:{env.https_port}" + + def test_h2_600_02(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}/", + ] + }) + conf.add_vhost_cgi() + conf.install() + assert env.apache_restart() == 0 + url = env.mkurl("https", "cgi", "/h2c/hello.py") + r = env.curl_get(url, 5) + assert r.response["status"] == 200 + assert r.response["json"]["protocol"] == "HTTP/2.0" + assert r.response["json"]["https"] == "" + # the proxied backend sees Host header as passed on front + assert r.response["json"]["x_host"] == f"cgi.{env.http_tld}:{env.https_port}" + + def test_h2_600_03(self, env): + conf = H2Conf(env, extras={ + f'cgi.{env.http_tld}': [ + "SetEnvIf Host (.+) X_HOST=$1", + f"ProxyPreserveHost off", + f"ProxyPass /h2c/ h2c://127.0.0.1:{env.http_port}/", + ] + }) + conf.add_vhost_cgi() + conf.install() + assert env.apache_restart() == 0 + url = env.mkurl("https", "cgi", "/h2c/hello.py") + r = env.curl_get(url, 5) + assert r.response["status"] == 200 + assert r.response["json"]["protocol"] == "HTTP/2.0" + assert r.response["json"]["https"] == "" + # the proxied backend sees Host as using in connecting to it + assert r.response["json"]["x_host"] == f"127.0.0.1:{env.http_port}" |