changeset 1467:d6062cccd4c0

server: better reverse proxy headers handling: reverse proxy header were not used if `X-Forwarded-Host` was not set, with this patch `X-Forwarded-Host` and `X-Forwarded-Proto` are check independently. Furthermore, the new standardised `Forwarded` header is not checked too. fix 396
author Goffi <goffi@goffi.org>
date Thu, 30 Sep 2021 18:40:49 +0200 (2021-09-30)
parents cff720e26089
children e85ef5f3515e
files libervia/server/server.py
diffstat 1 files changed, 27 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/libervia/server/server.py	Thu Sep 30 17:04:22 2021 +0200
+++ b/libervia/server/server.py	Thu Sep 30 18:40:49 2021 +0200
@@ -1656,41 +1656,36 @@
         """
         ext_data = self.base_url_ext_data
         url_path = request.URLPath()
-        if not ext_data.scheme or not ext_data.netloc:
-            #  ext_data is not specified, we check headers
-            if request.requestHeaders.hasHeader("x-forwarded-host"):
-                # we are behing a proxy
-                # we fill proxy_scheme and proxy_netloc value
-                proxy_host = request.requestHeaders.getRawHeaders("x-forwarded-host")[0]
-                try:
-                    proxy_server = request.requestHeaders.getRawHeaders(
-                        "x-forwarded-server"
-                    )[0]
-                except TypeError:
-                    # no x-forwarded-server found, we use proxy_host
-                    proxy_netloc = proxy_host
-                else:
-                    # if the proxy host has a port, we use it with server name
-                    proxy_port = urllib.parse.urlsplit("//{}".format(proxy_host)).port
-                    proxy_netloc = (
-                        "{}:{}".format(proxy_server, proxy_port)
-                        if proxy_port is not None
-                        else proxy_server
-                    )
-                try:
-                    proxy_scheme = request.requestHeaders.getRawHeaders(
-                        "x-forwarded-proto"
-                    )[0]
-                except TypeError:
-                    proxy_scheme = None
-            else:
-                proxy_scheme, proxy_netloc = None, None
+
+        try:
+            forwarded = request.requestHeaders.getRawHeaders(
+                "forwarded"
+            )[0]
+        except TypeError:
+            # we try deprecated headers
+            try:
+                proxy_netloc = request.requestHeaders.getRawHeaders(
+                    "x-forwarded-host"
+                )[0]
+            except TypeError:
+                proxy_netloc = None
+            try:
+                proxy_scheme = request.requestHeaders.getRawHeaders(
+                    "x-forwarded-proto"
+                )[0]
+            except TypeError:
+                proxy_scheme = None
         else:
-            proxy_scheme, proxy_netloc = None, None
+            fwd_data = {
+                k.strip(): v.strip()
+                for k,v in (d.split("=") for d in forwarded.split(";"))
+            }
+            proxy_netloc = fwd_data.get("host")
+            proxy_scheme = fwd_data.get("proto")
 
         return urllib.parse.SplitResult(
-            ext_data.scheme or proxy_scheme or url_path.scheme.decode("utf-8"),
-            ext_data.netloc or proxy_netloc or url_path.netloc.decode("utf-8"),
+            ext_data.scheme or proxy_scheme or url_path.scheme.decode(),
+            ext_data.netloc or proxy_netloc or url_path.netloc.decode(),
             ext_data.path or "/",
             "",
             "",