diff --git a/scm-core/src/main/java/sonia/scm/util/HttpUtil.java b/scm-core/src/main/java/sonia/scm/util/HttpUtil.java index 1e54b8a931..2d7d5ac9ba 100644 --- a/scm-core/src/main/java/sonia/scm/util/HttpUtil.java +++ b/scm-core/src/main/java/sonia/scm/util/HttpUtil.java @@ -35,6 +35,8 @@ package sonia.scm.util; //~--- non-JDK imports -------------------------------------------------------- +import com.google.common.base.Strings; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,6 +50,9 @@ import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -155,6 +160,10 @@ public class HttpUtil /** the logger for HttpUtil */ private static final Logger logger = LoggerFactory.getLogger(HttpUtil.class); + /** Field description */ + private static final Pattern PATTERN_URLNORMALIZE = + Pattern.compile("(?:(http://[^:]+):80(/.+)?|(https://[^:]+):443(/.+)?)"); + //~--- methods -------------------------------------------------------------- /** @@ -266,6 +275,51 @@ public class HttpUtil return value; } + /** + * Returns the normalized url. + * + * + * @param url to normalize + * + * @return normalized url + * + * @since 1.26 + */ + public static String normalizeUrl(String url) + { + if (!Strings.isNullOrEmpty(url)) + { + Matcher m = PATTERN_URLNORMALIZE.matcher(url); + + if (m.matches()) + { + String prefix = m.group(1); + String suffix; + + if (prefix == null) + { + prefix = m.group(3); + suffix = m.group(4); + } + else + { + suffix = m.group(2); + } + + if (suffix != null) + { + url = prefix.concat(suffix); + } + else + { + url = prefix; + } + } + } + + return url; + } + /** * Method description * diff --git a/scm-core/src/test/java/sonia/scm/util/HttpUtilTest.java b/scm-core/src/test/java/sonia/scm/util/HttpUtilTest.java index 155cfdac39..d2aa20a152 100644 --- a/scm-core/src/test/java/sonia/scm/util/HttpUtilTest.java +++ b/scm-core/src/test/java/sonia/scm/util/HttpUtilTest.java @@ -54,6 +54,33 @@ import javax.servlet.http.HttpServletRequest; public class HttpUtilTest { + /** + * Method description + * + */ + @Test + public void normalizeUrlTest() + { + assertEquals("http://www.scm-manager/scm", + HttpUtil.normalizeUrl("http://www.scm-manager/scm")); + assertEquals("http://www.scm-manager/scm", + HttpUtil.normalizeUrl("http://www.scm-manager:80/scm")); + assertEquals("https://www.scm-manager/scm", + HttpUtil.normalizeUrl("https://www.scm-manager:443/scm")); + assertEquals("https://www.scm-manager:8181/scm", + HttpUtil.normalizeUrl("https://www.scm-manager:8181/scm")); + assertEquals("http://www.scm-manager:8080/scm", + HttpUtil.normalizeUrl("http://www.scm-manager:8080/scm")); + assertEquals("http://www.scm-manager", + HttpUtil.normalizeUrl("http://www.scm-manager:80")); + assertEquals("https://www.scm-manager", + HttpUtil.normalizeUrl("https://www.scm-manager:443")); + assertEquals("http://www.scm-manager:8080", + HttpUtil.normalizeUrl("http://www.scm-manager:8080")); + } + + //~--- get methods ---------------------------------------------------------- + /** * Method description * @@ -65,9 +92,9 @@ public class HttpUtilTest config.setBaseUrl("http://www.scm-manager.org/scm"); assertEquals("http://www.scm-manager.org/scm/test/path", - HttpUtil.getCompleteUrl(config, "test/path")); + HttpUtil.getCompleteUrl(config, "test/path")); assertEquals("http://www.scm-manager.org/scm/test/path", - HttpUtil.getCompleteUrl(config, "/test/path")); + HttpUtil.getCompleteUrl(config, "/test/path")); } /** @@ -80,10 +107,10 @@ public class HttpUtilTest assertTrue(HttpUtil.getPortFromUrl("http://www.scm-manager.org") == 80); assertTrue(HttpUtil.getPortFromUrl("https://www.scm-manager.org") == 443); assertTrue(HttpUtil.getPortFromUrl("http://www.scm-manager.org:8080") - == 8080); + == 8080); assertTrue( - HttpUtil.getPortFromUrl("http://www.scm-manager.org:8181/test/folder") - == 8181); + HttpUtil.getPortFromUrl("http://www.scm-manager.org:8181/test/folder") + == 8181); } /** @@ -116,7 +143,7 @@ public class HttpUtilTest when(request.getRequestURI()).thenReturn("/scm/test/path"); when(request.getContextPath()).thenReturn("/scm"); assertEquals("/test/path", - HttpUtil.getStrippedURI(request, "/scm/test/path")); + HttpUtil.getStrippedURI(request, "/scm/test/path")); assertEquals("/test/path", HttpUtil.getStrippedURI(request)); } @@ -130,7 +157,7 @@ public class HttpUtilTest assertEquals("/test", HttpUtil.getUriWithoutEndSeperator("/test/")); assertEquals("/test/two", HttpUtil.getUriWithoutEndSeperator("/test/two/")); assertEquals("/test/two/three", - HttpUtil.getUriWithoutEndSeperator("/test/two/three")); + HttpUtil.getUriWithoutEndSeperator("/test/two/three")); } /** @@ -142,8 +169,8 @@ public class HttpUtilTest { assertEquals("test/", HttpUtil.getUriWithoutStartSeperator("/test/")); assertEquals("test/two/", - HttpUtil.getUriWithoutStartSeperator("/test/two/")); + HttpUtil.getUriWithoutStartSeperator("/test/two/")); assertEquals("test/two/three", - HttpUtil.getUriWithoutStartSeperator("test/two/three")); + HttpUtil.getUriWithoutStartSeperator("test/two/three")); } } diff --git a/scm-webapp/src/main/java/sonia/scm/filter/BaseUrlFilter.java b/scm-webapp/src/main/java/sonia/scm/filter/BaseUrlFilter.java index 1920943f57..f2397bbcc2 100644 --- a/scm-webapp/src/main/java/sonia/scm/filter/BaseUrlFilter.java +++ b/scm-webapp/src/main/java/sonia/scm/filter/BaseUrlFilter.java @@ -35,6 +35,7 @@ package sonia.scm.filter; //~--- non-JDK imports -------------------------------------------------------- +import com.google.common.annotations.VisibleForTesting; import com.google.inject.Inject; import com.google.inject.Singleton; @@ -74,6 +75,22 @@ public class BaseUrlFilter extends HttpFilter //~--- methods -------------------------------------------------------------- + /** + * Method description + * + * + * @param requestUrl + * @param baseUrl + * + * @return + */ + @VisibleForTesting + boolean startsWith(String requestUrl, String baseUrl) + { + return HttpUtil.normalizeUrl(requestUrl).startsWith( + HttpUtil.normalizeUrl(baseUrl)); + } + /** * Method description * @@ -87,8 +104,8 @@ public class BaseUrlFilter extends HttpFilter */ @Override protected void doFilter(HttpServletRequest request, - HttpServletResponse response, FilterChain chain) - throws IOException, ServletException + HttpServletResponse response, FilterChain chain) + throws IOException, ServletException { if (Util.isEmpty(configuration.getBaseUrl())) { @@ -139,8 +156,8 @@ public class BaseUrlFilter extends HttpFilter */ private boolean isBaseUrl(HttpServletRequest request) { - return request.getRequestURL().toString().startsWith( - configuration.getBaseUrl()); + return startsWith(request.getRequestURL().toString(), + configuration.getBaseUrl()); } //~--- fields --------------------------------------------------------------- diff --git a/scm-webapp/src/test/java/sonia/scm/filter/BaseUrlFilterTest.java b/scm-webapp/src/test/java/sonia/scm/filter/BaseUrlFilterTest.java new file mode 100644 index 0000000000..ac24cfd409 --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/filter/BaseUrlFilterTest.java @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.filter; + +//~--- non-JDK imports -------------------------------------------------------- + +import org.junit.Test; + +import sonia.scm.config.ScmConfiguration; + +import static org.junit.Assert.*; + +/** + * + * @author Sebastian Sdorra + */ +public class BaseUrlFilterTest +{ + + /** + * Method description + * + */ + @Test + public void startsWithTest() + { + BaseUrlFilter filter = new BaseUrlFilter(new ScmConfiguration()); + + assertTrue(filter.startsWith("http://www.scm-manager.org/scm", + "http://www.scm-manager.org/scm")); + assertTrue(filter.startsWith("http://www.scm-manager.org:80/scm", + "http://www.scm-manager.org/scm")); + assertTrue(filter.startsWith("https://www.scm-manager.org/scm", + "https://www.scm-manager.org:443/scm")); + assertFalse(filter.startsWith("http://www.scm-manager.org/acb", + "http://www.scm-manager.org/scm")); + } +}