diff --git a/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/hostport/GetHostPort.java b/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/hostport/GetHostPort.java new file mode 100644 index 000000000000..ab1cad192802 --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/hostport/GetHostPort.java @@ -0,0 +1,45 @@ +package com.baeldung.hostport; + +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +public class GetHostPort { + + public static String getHostWithPort(HttpServletRequest request) { + String scheme = request.getScheme(); + String serverName = request.getServerName(); + int serverPort = request.getServerPort(); + + boolean isDefaultPort = ("http".equals(scheme) && serverPort == 80) + || ("https".equals(scheme) && serverPort == 443); + + if (isDefaultPort) { + return String.format("%s://%s", scheme, serverName); + } else { + return String.format("%s://%s:%d", scheme, serverName, serverPort); + } + } + + public static String getBaseUrl() { + return ServletUriComponentsBuilder.fromCurrentRequestUri() + .replacePath(null) + .build() + .toUriString(); + } + + public static String getForwardedHost(HttpServletRequest request) { + String forwardedHost = request.getHeader("X-Forwarded-Host"); + String forwardedProto = request.getHeader("X-Forwarded-Proto"); + String forwardedPort = request.getHeader("X-Forwarded-Port"); + + String scheme = forwardedProto != null ? forwardedProto : request.getScheme(); + String host = forwardedHost != null ? forwardedHost : request.getServerName(); + String port = forwardedPort != null ? forwardedPort : String.valueOf(request.getServerPort()); + + boolean isDefaultPort = ("http".equals(scheme) && "80".equals(port)) + || ("https".equals(scheme) && "443".equals(port)); + + return isDefaultPort ? String.format("%s://%s", scheme, host) + : String.format("%s://%s:%s", scheme, host, port); + } +} diff --git a/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/hostport/GetHostPortUnitTest.java b/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/hostport/GetHostPortUnitTest.java new file mode 100644 index 000000000000..f47556c0cbf5 --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/hostport/GetHostPortUnitTest.java @@ -0,0 +1,117 @@ +package com.baeldung.hostport; + +import jakarta.servlet.http.HttpServletRequest; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.net.MalformedURLException; +import java.net.URL; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class GetHostPortUnitTest { + + @Test + void givenHttpWithDefaultPort_whenGetHostWithPort_thenReturnWithoutPort() { + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + Mockito.when(request.getScheme()).thenReturn("http"); + Mockito.when(request.getServerName()).thenReturn("example.com"); + Mockito.when(request.getServerPort()).thenReturn(80); + + String result = GetHostPort.getHostWithPort(request); + + assertEquals("http://example.com", result); + } + + @Test + void givenHttpsWithDefaultPort_whenGetHostWithPort_thenReturnWithoutPort() { + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + Mockito.when(request.getScheme()).thenReturn("https"); + Mockito.when(request.getServerName()).thenReturn("secure.example.com"); + Mockito.when(request.getServerPort()).thenReturn(443); + + String result = GetHostPort.getHostWithPort(request); + + assertEquals("https://secure.example.com", result); + } + + @Test + void givenHttpWithCustomPort_whenGetHostWithPort_thenIncludePort() { + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + Mockito.when(request.getScheme()).thenReturn("http"); + Mockito.when(request.getServerName()).thenReturn("localhost"); + Mockito.when(request.getServerPort()).thenReturn(8080); + + String result = GetHostPort.getHostWithPort(request); + + assertEquals("http://localhost:8080", result); + } + + @Test + void givenHttpsWithCustomPort_whenGetHostWithPort_thenIncludePort() { + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + Mockito.when(request.getScheme()).thenReturn("https"); + Mockito.when(request.getServerName()).thenReturn("test.example.com"); + Mockito.when(request.getServerPort()).thenReturn(8443); + + String result = GetHostPort.getHostWithPort(request); + + assertEquals("https://test.example.com:8443", result); + } + + @Test + void whenUsingServletUriComponentsBuilder_thenReturnBaseUrl() { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setScheme("https"); + request.setServerName("example.com"); + request.setServerPort(8443); + request.setRequestURI("/api/users/123"); + + RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request)); + String baseUrl = GetHostPort.getBaseUrl(); + + assertEquals("https://example.com:8443", baseUrl); + + RequestContextHolder.resetRequestAttributes(); + } + + @Test + void givenRequestURL_whenParse_thenExtractHostWithPort() throws MalformedURLException { + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://localhost:8080/api/test")); + + URL url = new URL(request.getRequestURL().toString()); + String hostWithPort = url.getPort() == -1 + ? String.format("%s://%s", url.getProtocol(), url.getHost()) + : String.format("%s://%s:%d", url.getProtocol(), url.getHost(), url.getPort()); + + assertEquals("http://localhost:8080", hostWithPort); + } + + @Test + void givenForwardedHeaders_whenGetForwardedHost_thenReturnProxyHost() { + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + Mockito.when(request.getHeader("X-Forwarded-Host")).thenReturn("proxy.example.com"); + Mockito.when(request.getHeader("X-Forwarded-Proto")).thenReturn("https"); + Mockito.when(request.getHeader("X-Forwarded-Port")).thenReturn("443"); + + String result = GetHostPort.getForwardedHost(request); + + assertEquals("https://proxy.example.com", result); + } + + @Test + void givenNoForwardedHeaders_whenGetForwardedHost_thenUseRequestValues() { + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + Mockito.when(request.getScheme()).thenReturn("http"); + Mockito.when(request.getServerName()).thenReturn("localhost"); + Mockito.when(request.getServerPort()).thenReturn(8080); + + String result = GetHostPort.getForwardedHost(request); + + assertEquals("http://localhost:8080", result); + } +}