Files
shz-backend/ruoyi-common/src/main/java/com/ruoyi/common/utils/RequestUrlUtils.java

189 lines
6.5 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.ruoyi.common.utils;
import javax.servlet.http.HttpServletRequest;
/**
* 请求公开地址工具。
*
* <p>应用位于反向代理后时Servlet 请求看到的 serverName/serverPort 可能是代理的内网地址,
* 因此优先使用代理传递的公开地址,再回退到 Host 和 Servlet 请求信息。</p>
*/
public final class RequestUrlUtils
{
/** 反向代理未透传公开地址时使用的默认访问地址(不带末尾斜杠,便于拼接路径)。 */
private static final String DEFAULT_PUBLIC_BASE_URL = "http://39.98.44.136:6024/shihezi";
private RequestUrlUtils()
{
}
public static String buildBaseUrl(HttpServletRequest request)
{
if (request == null) {
return "";
}
String forwardedHeader = request.getHeader("Forwarded");
String forwarded = firstForwardedValue(forwardedHeader, "host");
String forwardedHost = firstHeaderValue(request.getHeader("X-Forwarded-Host"));
String hostHeader = request.getHeader("Host");
String requestHost = firstNonBlank(hostHeader, request.getServerName());
String forwardedPublicHost = firstNonBlank(forwarded, forwardedHost);
if (isInternalHost(requestHost) && isInternalHost(forwardedPublicHost)) {
String contextPath = request.getContextPath();
return DEFAULT_PUBLIC_BASE_URL + (contextPath == null ? "" : contextPath);
}
boolean hasPublicHost = !isBlank(forwarded) || !isBlank(forwardedHost)
|| !isBlank(hostHeader);
String host = firstNonBlank(
forwarded,
forwardedHost,
hostHeader,
request.getServerName());
host = normalizeHost(host);
String scheme = firstNonBlank(
firstForwardedValue(request.getHeader("Forwarded"), "proto"),
firstHeaderValue(request.getHeader("X-Forwarded-Proto")),
request.getScheme());
scheme = normalizeScheme(scheme, request.getScheme());
String forwardedPort = firstNonBlank(
extractPort(forwarded),
firstHeaderValue(request.getHeader("X-Forwarded-Port")));
if (!hasPort(host) && shouldIncludePort(forwardedPort, scheme)) {
host += ":" + forwardedPort;
}
if (!hasPort(host) && isBlank(forwardedPort) && !hasPublicHost
&& shouldIncludePort(String.valueOf(request.getServerPort()), scheme)) {
host += ":" + request.getServerPort();
}
String contextPath = request.getContextPath();
return scheme + "://" + host + (contextPath == null ? "" : contextPath);
}
private static boolean isInternalHost(String host)
{
if (isBlank(host)) {
return true;
}
String normalized = host.trim().toLowerCase();
if (normalized.startsWith("[") && normalized.contains("]")) {
normalized = normalized.substring(1, normalized.indexOf(']'));
} else if (normalized.indexOf(':') == normalized.lastIndexOf(':')) {
normalized = normalized.substring(0, normalized.indexOf(':'));
}
return "localhost".equals(normalized)
|| "127.0.0.1".equals(normalized)
|| "0.0.0.0".equals(normalized)
|| "::1".equals(normalized);
}
private static String firstForwardedValue(String header, String name)
{
if (isBlank(header)) {
return null;
}
String firstElement = header.split(",", 2)[0];
String[] parameters = firstElement.split(";");
for (String parameter : parameters) {
String[] pair = parameter.split("=", 2);
if (pair.length == 2 && name.equalsIgnoreCase(pair[0].trim())) {
return stripQuotes(pair[1].trim());
}
}
return null;
}
private static String firstHeaderValue(String header)
{
if (isBlank(header)) {
return null;
}
return stripQuotes(header.split(",", 2)[0].trim());
}
private static String normalizeHost(String host)
{
if (isBlank(host)) {
return "localhost";
}
String normalized = stripQuotes(host.trim());
if (normalized.indexOf('\r') >= 0 || normalized.indexOf('\n') >= 0
|| normalized.indexOf('/') >= 0 || normalized.indexOf('?') >= 0
|| normalized.indexOf('#') >= 0) {
return "localhost";
}
return normalized;
}
private static String normalizeScheme(String scheme, String fallback)
{
if ("https".equalsIgnoreCase(scheme)) {
return "https";
}
if ("http".equalsIgnoreCase(scheme)) {
return "http";
}
return "https".equalsIgnoreCase(fallback) ? "https" : "http";
}
private static String extractPort(String host)
{
if (isBlank(host)) {
return null;
}
String normalized = host.trim();
if (normalized.startsWith("[") && normalized.contains("]:")) {
return normalized.substring(normalized.lastIndexOf(':') + 1);
}
int colon = normalized.lastIndexOf(':');
return colon > -1 && normalized.indexOf(':') == colon
? normalized.substring(colon + 1) : null;
}
private static boolean hasPort(String host)
{
return !isBlank(extractPort(host));
}
private static boolean shouldIncludePort(String port, String scheme)
{
if (isBlank(port)) {
return false;
}
try {
int portNumber = Integer.parseInt(port);
return portNumber > 0 && portNumber <= 65535
&& !(("http".equalsIgnoreCase(scheme) && portNumber == 80)
|| ("https".equalsIgnoreCase(scheme) && portNumber == 443));
} catch (NumberFormatException e) {
return false;
}
}
private static String firstNonBlank(String... values)
{
for (String value : values) {
if (!isBlank(value)) {
return value.trim();
}
}
return null;
}
private static String stripQuotes(String value)
{
if (value != null && value.length() >= 2 && value.startsWith("\"") && value.endsWith("\"")) {
return value.substring(1, value.length() - 1);
}
return value;
}
private static boolean isBlank(String value)
{
return value == null || value.trim().isEmpty();
}
}