From 201e3c3fecaa0fa068d5f63b6073ee3f1ba0ad73 Mon Sep 17 00:00:00 2001 From: Mathieu Date: Sat, 3 Dec 2022 08:22:19 +0100 Subject: [PATCH] Support Via header, removing requirement of supporting ProxyPreserverHost --- .../org/argeo/cms/servlet/ServletUtils.java | 52 +++++++++++++++++++ .../src/org/argeo/cms/http/HttpHeader.java | 6 ++- .../org/argeo/cms/http/HttpServerUtils.java | 1 + 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 org.argeo.cms.ee/src/org/argeo/cms/servlet/ServletUtils.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 index 000000000..072417a8a --- /dev/null +++ b/org.argeo.cms.ee/src/org/argeo/cms/servlet/ServletUtils.java @@ -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 viaHosts = new ArrayList<>(); + for (Enumeration 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() { + } +} diff --git a/org.argeo.cms/src/org/argeo/cms/http/HttpHeader.java b/org.argeo.cms/src/org/argeo/cms/http/HttpHeader.java index 217b7a48a..ef7385d1d 100644 --- a/org.argeo.cms/src/org/argeo/cms/http/HttpHeader.java +++ b/org.argeo.cms/src/org/argeo/cms/http/HttpHeader.java @@ -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"; diff --git a/org.argeo.cms/src/org/argeo/cms/http/HttpServerUtils.java b/org.argeo.cms/src/org/argeo/cms/http/HttpServerUtils.java index fc04fbfaa..46f29229b 100644 --- a/org.argeo.cms/src/org/argeo/cms/http/HttpServerUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/http/HttpServerUtils.java @@ -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 = "/"; -- 2.30.2