mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-03-17 09:40:25 +01:00
merge with branch issue-748
This commit is contained in:
@@ -35,7 +35,9 @@ package sonia.scm.util;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -97,6 +99,24 @@ public final class HttpUtil
|
||||
/** authentication header */
|
||||
public static final String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
|
||||
|
||||
/**
|
||||
* The original host requested by the client in the Host HTTP request header.
|
||||
* @since 1.47
|
||||
*/
|
||||
public static final String HEADER_X_FORWARDED_HOST = "X-Forwarded-Host";
|
||||
|
||||
/**
|
||||
* The original port requested by the client.
|
||||
* @since 1.47
|
||||
*/
|
||||
public static final String HEADER_X_FORWARDED_PORT = "X-Forwarded-Port";
|
||||
|
||||
/**
|
||||
* The original protocol (http or https) requested by the client.
|
||||
* @since 1.47
|
||||
*/
|
||||
public static final String HEADER_X_FORWARDED_PROTO = "X-Forwarded-Proto";
|
||||
|
||||
/**
|
||||
* Default http port
|
||||
* @since 1.5
|
||||
@@ -579,21 +599,31 @@ public final class HttpUtil
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns an absolute url with context path.
|
||||
* Returns an absolute url with context path. The method creates the url from
|
||||
* forwarding request headers, if they are available.
|
||||
*
|
||||
*
|
||||
* @param request http client request
|
||||
* @param pathSegments
|
||||
*
|
||||
* @return absolute url with context path
|
||||
*
|
||||
* @see <a href="https://goo.gl/PvGQyH">Issue 748</a>
|
||||
* @since 1.16
|
||||
*/
|
||||
public static String getCompleteUrl(HttpServletRequest request,
|
||||
String... pathSegments)
|
||||
{
|
||||
String baseUrl =
|
||||
request.getRequestURL().toString().replace(request.getRequestURI(),
|
||||
Util.EMPTY_STRING).concat(request.getContextPath());
|
||||
String baseUrl;
|
||||
|
||||
if (isForwarded(request))
|
||||
{
|
||||
baseUrl = createForwardedBaseUrl(request);
|
||||
}
|
||||
else
|
||||
{
|
||||
baseUrl = createBaseUrl(request);
|
||||
}
|
||||
|
||||
if (Util.isNotEmpty(pathSegments))
|
||||
{
|
||||
@@ -623,6 +653,24 @@ public final class HttpUtil
|
||||
return append(configuration.getBaseUrl(), path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
* @param header
|
||||
* @param defaultValue
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getHeader(HttpServletRequest request, String header,
|
||||
String defaultValue)
|
||||
{
|
||||
String value = request.getHeader(header);
|
||||
|
||||
return Objects.firstNonNull(value, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the port of the url parameter.
|
||||
*
|
||||
@@ -777,6 +825,21 @@ public final class HttpUtil
|
||||
return "chunked".equals(request.getHeader("Transfer-Encoding"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the request is forwarded by a reverse proxy. The
|
||||
* method uses the X-Forwarded-Host header to identify a forwarded request.
|
||||
*
|
||||
* @param request servlet request
|
||||
*
|
||||
* @return {@code true} if the request is forwarded
|
||||
*
|
||||
* @since 1.47
|
||||
*/
|
||||
public static boolean isForwarded(HttpServletRequest request)
|
||||
{
|
||||
return !Strings.isNullOrEmpty(request.getHeader(HEADER_X_FORWARDED_HOST));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the http request is send by the scm-manager web interface.
|
||||
*
|
||||
@@ -791,4 +854,74 @@ public final class HttpUtil
|
||||
return SCM_CLIENT_WUI.equalsIgnoreCase(
|
||||
request.getHeader(HEADER_SCM_CLIENT));
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Creates base url for request url.
|
||||
*
|
||||
* @param request http servlet request
|
||||
*
|
||||
* @return base url from request
|
||||
*
|
||||
* @since 1.47
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static String createBaseUrl(HttpServletRequest request)
|
||||
{
|
||||
return request.getRequestURL().toString().replace(request.getRequestURI(),
|
||||
Util.EMPTY_STRING).concat(request.getContextPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates base url from forwarding request headers.
|
||||
*
|
||||
* @param request http servlet request
|
||||
*
|
||||
* @return base url from forward headers
|
||||
*
|
||||
* @since 1.47
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static String createForwardedBaseUrl(HttpServletRequest request)
|
||||
{
|
||||
String proto = getHeader(request, HEADER_X_FORWARDED_PROTO,
|
||||
request.getScheme());
|
||||
String host;
|
||||
String fhost = getHeader(request, HEADER_X_FORWARDED_HOST,
|
||||
request.getScheme());
|
||||
String port = request.getHeader(HEADER_X_FORWARDED_PORT);
|
||||
int s = fhost.indexOf(SEPARATOR_PORT);
|
||||
|
||||
if (s > 0)
|
||||
{
|
||||
host = fhost.substring(0, s);
|
||||
|
||||
if (Strings.isNullOrEmpty(port))
|
||||
{
|
||||
port = fhost.substring(s + 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
host = fhost;
|
||||
}
|
||||
|
||||
StringBuilder buffer = new StringBuilder(proto);
|
||||
|
||||
buffer.append(SEPARATOR_SCHEME).append(host).append(SEPARATOR_PORT);
|
||||
|
||||
if (Strings.isNullOrEmpty(port))
|
||||
{
|
||||
buffer.append(String.valueOf(request.getServerPort()));
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.append(port);
|
||||
}
|
||||
|
||||
buffer.append(request.getContextPath());
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,6 +168,136 @@ public class HttpUtilTest
|
||||
HttpUtil.checkForCRLFInjection("abcka");
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testCreateBaseUrl()
|
||||
{
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
String url = "https://www.scm-manager.org/test/as/db";
|
||||
|
||||
when(request.getRequestURL()).thenReturn(new StringBuffer(url));
|
||||
when(request.getRequestURI()).thenReturn("/test/as/db");
|
||||
when(request.getContextPath()).thenReturn("/scm");
|
||||
assertEquals("https://www.scm-manager.org/scm",
|
||||
HttpUtil.createBaseUrl(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testCreateForwardedUrl()
|
||||
{
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
|
||||
when(request.getHeader(HttpUtil.HEADER_X_FORWARDED_HOST)).thenReturn(
|
||||
"www.scm-manager.org");
|
||||
when(request.getHeader(HttpUtil.HEADER_X_FORWARDED_PROTO)).thenReturn(
|
||||
"https");
|
||||
when(request.getHeader(HttpUtil.HEADER_X_FORWARDED_PORT)).thenReturn("443");
|
||||
when(request.getContextPath()).thenReturn("/scm");
|
||||
assertEquals("https://www.scm-manager.org:443/scm",
|
||||
HttpUtil.createForwardedBaseUrl(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testCreateForwardedUrlWithPortAndProtoFromRequest()
|
||||
{
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
|
||||
when(request.getHeader(HttpUtil.HEADER_X_FORWARDED_HOST)).thenReturn(
|
||||
"www.scm-manager.org");
|
||||
when(request.getScheme()).thenReturn("https");
|
||||
when(request.getServerPort()).thenReturn(443);
|
||||
when(request.getContextPath()).thenReturn("/scm");
|
||||
assertEquals("https://www.scm-manager.org:443/scm",
|
||||
HttpUtil.createForwardedBaseUrl(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testCreateForwardedUrlWithPortInHost()
|
||||
{
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
|
||||
when(request.getHeader(HttpUtil.HEADER_X_FORWARDED_HOST)).thenReturn(
|
||||
"www.scm-manager.org:443");
|
||||
when(request.getHeader(HttpUtil.HEADER_X_FORWARDED_PROTO)).thenReturn(
|
||||
"https");
|
||||
when(request.getContextPath()).thenReturn("/scm");
|
||||
assertEquals("https://www.scm-manager.org:443/scm",
|
||||
HttpUtil.createForwardedBaseUrl(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testCreateForwardedUrlWithPortInHostAndPortHeader()
|
||||
{
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
|
||||
when(request.getHeader(HttpUtil.HEADER_X_FORWARDED_HOST)).thenReturn(
|
||||
"www.scm-manager.org:80");
|
||||
when(request.getHeader(HttpUtil.HEADER_X_FORWARDED_PROTO)).thenReturn(
|
||||
"https");
|
||||
when(request.getHeader(HttpUtil.HEADER_X_FORWARDED_PORT)).thenReturn("443");
|
||||
when(request.getContextPath()).thenReturn("/scm");
|
||||
assertEquals("https://www.scm-manager.org:443/scm",
|
||||
HttpUtil.createForwardedBaseUrl(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testGetCompleteUrl()
|
||||
{
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
String url = "https://www.scm-manager.org/test/as/db";
|
||||
|
||||
when(request.getRequestURL()).thenReturn(new StringBuffer(url));
|
||||
when(request.getRequestURI()).thenReturn("/test/as/db");
|
||||
when(request.getScheme()).thenReturn("https");
|
||||
when(request.getServerPort()).thenReturn(443);
|
||||
when(request.getContextPath()).thenReturn("/scm");
|
||||
assertEquals("https://www.scm-manager.org/scm",
|
||||
HttpUtil.getCompleteUrl(request));
|
||||
when(request.getHeader(HttpUtil.HEADER_X_FORWARDED_HOST)).thenReturn(
|
||||
"scm.scm-manager.org");
|
||||
assertEquals("https://scm.scm-manager.org:443/scm",
|
||||
HttpUtil.getCompleteUrl(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testIsForwarded()
|
||||
{
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
|
||||
assertFalse(HttpUtil.isForwarded(request));
|
||||
when(request.getHeader(HttpUtil.HEADER_X_FORWARDED_HOST)).thenReturn("");
|
||||
assertFalse(HttpUtil.isForwarded(request));
|
||||
when(request.getHeader(HttpUtil.HEADER_X_FORWARDED_HOST)).thenReturn("ser");
|
||||
assertTrue(HttpUtil.isForwarded(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user