Support Via header, removing requirement of supporting
authorMathieu <mbaudier@argeo.org>
Sat, 3 Dec 2022 07:22:19 +0000 (08:22 +0100)
committerMathieu <mbaudier@argeo.org>
Sat, 3 Dec 2022 07:22:19 +0000 (08:22 +0100)
ProxyPreserverHost

org.argeo.cms.ee/src/org/argeo/cms/servlet/ServletUtils.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/http/HttpHeader.java
org.argeo.cms/src/org/argeo/cms/http/HttpServerUtils.java

diff --git a/org.argeo.cms.ee/src/org/argeo/cms/servlet/ServletUtils.java b/org.argeo.cms.ee/src/org/argeo/cms/servlet/ServletUtils.java
new file mode 100644 (file)
index 0000000..072417a
--- /dev/null
@@ -0,0 +1,52 @@
+package org.argeo.cms.servlet;
+
+import static org.argeo.cms.http.HttpHeader.VIA;
+import static org.argeo.cms.http.HttpHeader.X_FORWARDED_HOST;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+/** Servlet utilities. */
+public class ServletUtils {
+
+       /**
+        * The base URL for this query (without any path component (not even an ending
+        * '/'), taking into account reverse proxies.
+        */
+       public static StringBuilder getRequestUrlBase(HttpServletRequest req) {
+               List<String> viaHosts = new ArrayList<>();
+               for (Enumeration<String> it = req.getHeaders(VIA.getHeaderName()); it.hasMoreElements();) {
+                       String[] arr = it.nextElement().split(" ");
+                       viaHosts.add(arr[1]);
+               }
+
+               String outerHost = viaHosts.isEmpty() ? null : viaHosts.get(0);
+               if (outerHost == null) {
+                       // Try non-standard header
+                       String forwardedHost = req.getHeader(X_FORWARDED_HOST.getHeaderName());
+                       if (forwardedHost != null) {
+                               String[] arr = forwardedHost.split(",");
+                               outerHost = arr[0];
+                       }
+               }
+
+               URI requestUrl = URI.create(req.getRequestURL().toString());
+
+               boolean isReverseProxy = outerHost != null && !outerHost.equals(requestUrl.getHost());
+               if (isReverseProxy) {
+                       String protocol = req.isSecure() ? "https" : "http";
+                       return new StringBuilder(protocol + "://" + outerHost);
+               } else {
+                       return new StringBuilder(requestUrl.getScheme() + "://" + requestUrl.getHost()
+                                       + (requestUrl.getPort() > 0 ? ":" + requestUrl.getPort() : ""));
+               }
+       }
+
+       /** singleton */
+       private ServletUtils() {
+       }
+}
index 217b7a48aa4a63c8cc00765330cf1cd2875678ba..ef7385d1d5516899100c4c30648582bf593c3ff7 100644 (file)
@@ -1,14 +1,18 @@
 package org.argeo.cms.http;
 
-/** Standard HTTP headers (including WebDav). */
+/** Selection of standard or common HTTP headers (including WebDav). */
 public enum HttpHeader {
        AUTHORIZATION("Authorization"), //
        WWW_AUTHENTICATE("WWW-Authenticate"), //
        ALLOW("Allow"), //
+       VIA("Via"), //
 
        // WebDav
        DAV("DAV"), //
        DEPTH("Depth"), //
+
+       // Non-standard
+       X_FORWARDED_HOST("X-Forwarded-Host"), //
        ;
 
        public final static String BASIC = "Basic";
index fc04fbfaa7cff5e01d835b20507a08e8b53678a0..46f29229b7508546c4dc127d09ceb85410305a81 100644 (file)
@@ -6,6 +6,7 @@ import java.util.Objects;
 import com.sun.net.httpserver.HttpContext;
 import com.sun.net.httpserver.HttpExchange;
 
+/** HTTP utilities on the server-side. */
 public class HttpServerUtils {
        private final static String SLASH = "/";