]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Merge of /httpd/httpd/trunk:r1912180
authorStefan Eissing <icing@apache.org>
Fri, 8 Sep 2023 13:23:00 +0000 (13:23 +0000)
committerStefan Eissing <icing@apache.org>
Fri, 8 Sep 2023 13:23:00 +0000 (13:23 +0000)
  *) mod_proxy_http2: fix `X-Forward-Host` header to carry the correct value.
     Fixes PR66752.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1912194 13f79535-47bb-0310-9956-ffa450edef68

STATUS
changes-entries/h2_proxy_forwarded_host.txt [new file with mode: 0644]
modules/http2/h2_proxy_session.c
test/modules/http2/htdocs/cgi/hello.py
test/modules/http2/test_600_h2proxy.py

diff --git a/STATUS b/STATUS
index c5a7e0da70b1b6d35b410bd4f5f8d50bbc756c42..4fd90979937abb16f7ab89a83de66085ce3333db 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -206,14 +206,6 @@ PATCHES PROPOSED TO BACKPORT FROM TRUNK:
         svn merge -c 1912015 ^/httpd/httpd/trunk .
      +1: rjung, gbechis
 
-  *) mod_proxy_http2: fix `X-Forward-Host` header to carry the correct value.
-     Fixes PR66752.
-     Trunk version of patch:
-        https://svn.apache.org/r1912180
-     Backport version for 2.4.x of patch:
-      svn merge -c 1912180 ^/httpd/httpd/trunk .
-     +1: icing,
-
 PATCHES/ISSUES THAT ARE BEING WORKED
   [ New entries should be added at the START of the list ]
 
diff --git a/changes-entries/h2_proxy_forwarded_host.txt b/changes-entries/h2_proxy_forwarded_host.txt
new file mode 100644 (file)
index 0000000..3389353
--- /dev/null
@@ -0,0 +1,4 @@
+  *) mod_proxy_http2: fix `X-Forward-Host` header to carry the correct value.
+     Fixes PR66752.
+     [Stefan Eissing]
+
index 8a5c591ab8255d90a31fd9c651e953ecd4ec4f0e..db2230127667811631598aae01095eeea1968ddf 100644 (file)
@@ -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;
 
@@ -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;
@@ -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.
              */
@@ -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
index 20974bfdd3f143dd3a0f49ab33f2b24bfad99305..a96da8aafb128c7eca64008588227876fe5c32cb 100644 (file)
@@ -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))
 
index cfcea45602d1a0022b06fe2fb8ee895bfe7776b2..040aef6515eba987832550878a727b06b8c6de75 100644 (file)
@@ -136,6 +136,28 @@ class TestH2Proxy:
             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)