You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2013/04/30 17:23:41 UTC
svn commit: r1477686 - in /cxf/trunk/rt/frontend/jaxrs/src:
main/java/org/apache/cxf/jaxrs/utils/ test/java/org/apache/cxf/jaxrs/impl/
test/java/org/apache/cxf/jaxrs/utils/
Author: sergeyb
Date: Tue Apr 30 15:23:40 2013
New Revision: 1477686
URL: http://svn.apache.org/r1477686
Log:
[CXF-4919] Fixing UriInfo/HttpUtils relativize implementation, quality patch from Stian Soiland-Reyes applied
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/LinkBuilderImplTest.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/HttpUtilsTest.java
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java?rev=1477686&r1=1477685&r2=1477686&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java Tue Apr 30 15:23:40 2013
@@ -495,44 +495,51 @@ public final class HttpUtils {
return uri;
}
- public static URI relativize(URI requestURI, URI resolved) {
- if (!getUriPrefix(resolved).equals(getUriPrefix(requestURI))) {
- return resolved;
+ public static URI relativize(URI base, URI uri) {
+ // quick bail-out
+ if (!(base.isAbsolute()) || !(uri.isAbsolute())) {
+ return uri;
+ }
+ if (base.isOpaque() || uri.isOpaque()) {
+ // Unlikely case of an URN which can't deal with
+ // relative path, such as urn:isbn:0451450523
+ return uri;
+ }
+ // Check for common root
+ URI root = base.resolve("/");
+ if (!(root.equals(uri.resolve("/")))) {
+ // Different protocol/auth/host/port, return as is
+ return uri;
}
- List<PathSegment> resolvedSegments = JAXRSUtils.getPathSegments(resolved.getRawPath(), false);
- List<PathSegment> requestSegments = JAXRSUtils.getPathSegments(requestURI.getRawPath(), false);
- int count = 0;
- for (int i = resolvedSegments.size() - 1; i >= 0; i--) {
- if (i <= requestSegments.size() - 1) {
- String resolvedPath = resolvedSegments.get(i).getPath();
- String requestPath = requestSegments.get(i).getPath();
- if (!resolvedPath.equals(requestPath)) {
- count++;
- }
- }
+ // Ignore hostname bits for the following , but add "/" in the beginning
+ // so that in worst case we'll still return "/fred" rather than
+ // "http://example.com/fred".
+ URI baseRel = URI.create("/").resolve(root.relativize(base));
+ URI uriRel = URI.create("/").resolve(root.relativize(uri));
+
+ // Is it same path?
+ if (baseRel.getPath().equals(uriRel.getPath())) {
+ return baseRel.relativize(uriRel);
}
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < count; i++) {
- if (i != 0) {
- sb.append("/");
- }
- sb.append(PARENT_PATH_SEGMENT);
- }
- for (int i = count + 1; i < resolvedSegments.size(); i++) {
- if (i != 0) {
- sb.append("/");
- }
- sb.append(resolvedSegments.get(i).getPath());
+ // Direct siblings? (ie. in same folder)
+ URI commonBase = baseRel.resolve("./");
+ if (commonBase.equals(uriRel.resolve("./"))) {
+ return commonBase.relativize(uriRel);
}
- return URI.create(sb.toString());
- }
-
- private static String getUriPrefix(URI uri) {
- StringBuilder sb = new StringBuilder();
- sb.append(uri.getScheme()).append(uri.getHost()).append(uri.getPort());
- return sb.toString();
+ // No, then just keep climbing up until we find a common base.
+ URI relative = URI.create("");
+ while (!(uriRel.getPath().startsWith(commonBase.getPath())) && !(commonBase.getPath().equals("/"))) {
+ commonBase = commonBase.resolve("../");
+ relative = relative.resolve("../");
+ }
+
+ // Now we can use URI.relativize
+ URI relToCommon = commonBase.relativize(uriRel);
+ // and prepend the needed ../
+ return relative.resolve(relToCommon);
+
}
}
Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/LinkBuilderImplTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/LinkBuilderImplTest.java?rev=1477686&r1=1477685&r2=1477686&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/LinkBuilderImplTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/LinkBuilderImplTest.java Tue Apr 30 15:23:40 2013
@@ -22,7 +22,6 @@ import java.net.URI;
import javax.ws.rs.core.Link;
-import org.junit.Ignore;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
@@ -37,7 +36,6 @@ public class LinkBuilderImplTest {
assertEquals("<http://example.com/page1>;rel=\"previous\"", prevLink.toString());
}
- @Ignore("Ignored due to CXF-4919")
@Test
public void relativeBuild() throws Exception {
Link.Builder linkBuilder = new LinkBuilderImpl();
@@ -64,7 +62,6 @@ public class LinkBuilderImplTest {
assertEquals("<http://example.com/page3>;rel=\"next\"", nextLink.toString());
}
- @Ignore("Ignored due to CXF-4919")
@Test
public void copyOnRelativeBuild() throws Exception {
Link.Builder linkBuilder = new LinkBuilderImpl();
Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java?rev=1477686&r1=1477685&r2=1477686&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java Tue Apr 30 15:23:40 2013
@@ -75,10 +75,131 @@ public class UriInfoImplTest extends Ass
assertEquals("Wrong Request Uri", "http://localhost:8080/app/root/a/b/c",
u.getRequestUri().toString());
URI relativized = u.relativize(URI.create("http://localhost:8080/app/root/a/d/e"));
- assertEquals("../../d/e", relativized.toString());
+ assertEquals("../d/e", relativized.toString());
}
@Test
+ public void testRelativizeAlreadyRelative() throws Exception {
+ Message mockMessage = mockMessage("http://localhost:8080/app/root/",
+ "/soup/");
+ UriInfoImpl u = new UriInfoImpl(mockMessage, null);
+ assertEquals("http://localhost:8080/app/root/soup/", u.getRequestUri()
+ .toString());
+ URI x = URI.create("x/");
+ assertEquals("http://localhost:8080/app/root/x/", u.resolve(x)
+ .toString());
+ assertEquals("../x/", u.relativize(x).toString());
+ }
+
+ @Test
+ public void testRelativizeNoCommonPrefix() throws Exception {
+ Message mockMessage = mockMessage("http://localhost:8080/app/root/",
+ "/soup");
+ UriInfoImpl u = new UriInfoImpl(mockMessage, null);
+ assertEquals("http://localhost:8080/app/root/soup", u.getRequestUri()
+ .toString());
+ URI otherHost = URI.create("http://localhost:8081/app/root/x");
+ assertEquals(otherHost, u.resolve(otherHost));
+
+ // port/host is different!
+ assertEquals(otherHost, u.relativize(otherHost));
+ }
+
+ @Test
+ public void testRelativizeChild() throws Exception {
+ /** From UriInfo.relativize() javadoc (2013-04-21):
+*
+* <br/><b>Request URI:</b> <tt>http://host:port/app/root/a/b/c</tt>
+* <br/><b>Supplied URI:</b> <tt>a/b/c/d/e</tt>
+* <br/><b>Returned URI:</b> <tt>d/e</tt>
+*
+* NOTE: Although the above is correct JAX-RS API-wise (as of 2013-04-21),
+* it is WRONG URI-wise (but correct API wise)
+* as the request URI is missing the trailing / -- if the request returned HTML at
+* that location, then resolving "d/e" would end up instead at /app/root/a/b/d/e
+* -- see URI.create("/app/root/a/b/c").resolve("d/e"). Therefore the below tests
+* use the slightly modified request URI http://example.com/app/root/a/b/c/ with a trailing /
+*
+* See the test testRelativizeSibling for a non-slash-ending request URI
+*/
+ Message mockMessage = mockMessage("http://example.com/app/root/",
+ "/a/b/c/");
+ UriInfoImpl u = new UriInfoImpl(mockMessage, null);
+ assertEquals("http://example.com/app/root/a/b/c/", u.getRequestUri()
+ .toString());
+ URI absolute = URI.create("http://example.com/app/root/a/b/c/d/e");
+ assertEquals("d/e", u.relativize(absolute).toString());
+
+ URI relativeToBase = URI.create("a/b/c/d/e");
+ assertEquals("d/e", u.relativize(relativeToBase).toString());
+ }
+
+ @Test
+ public void testRelativizeSibling() throws Exception {
+ Message mockMessage = mockMessage("http://example.com/app/root/",
+ "/a/b/c.html");
+ UriInfoImpl u = new UriInfoImpl(mockMessage, null);
+ // NOTE: No slash in the end!
+ assertEquals("http://example.com/app/root/a/b/c.html", u
+ .getRequestUri().toString());
+ URI absolute = URI.create("http://example.com/app/root/a/b/c.pdf");
+ assertEquals("c.pdf", u.relativize(absolute).toString());
+
+ URI relativeToBase = URI.create("a/b/c.pdf");
+ assertEquals("c.pdf", u.relativize(relativeToBase).toString());
+ }
+
+ @Test
+ public void testRelativizeGrandParent() throws Exception {
+ Message mockMessage = mockMessage("http://example.com/app/root/",
+ "/a/b/c/");
+ UriInfoImpl u = new UriInfoImpl(mockMessage, null);
+ // NOTE: All end with slashes (imagine they are folders)
+ assertEquals("http://example.com/app/root/a/b/c/", u.getRequestUri()
+ .toString());
+ URI absolute = URI.create("http://example.com/app/root/a/");
+ // Need to go two levels up from /a/b/c/ to /a/
+ assertEquals("../../", u.relativize(absolute).toString());
+
+ URI relativeToBase = URI.create("a/");
+ assertEquals("../../", u.relativize(relativeToBase).toString());
+ }
+
+ @Test
+ public void testRelativizeCousin() throws Exception {
+ Message mockMessage = mockMessage("http://example.com/app/root/",
+ "/a/b/c/");
+ UriInfoImpl u = new UriInfoImpl(mockMessage, null);
+ // NOTE: All end with slashes (imagine they are folders)
+ assertEquals("http://example.com/app/root/a/b/c/", u.getRequestUri()
+ .toString());
+ URI absolute = URI.create("http://example.com/app/root/a/b2/c2/");
+ // Need to go two levels up from /a/b/c/ to /a/
+ assertEquals("../../b2/c2/", u.relativize(absolute).toString());
+
+ URI relativeToBase = URI.create("a/b2/c2/");
+ assertEquals("../../b2/c2/", u.relativize(relativeToBase).toString());
+ }
+
+ @Test
+ public void testRelativizeOutsideBase() throws Exception {
+ Message mockMessage = mockMessage("http://example.com/app/root/",
+ "/a/b/c/");
+ UriInfoImpl u = new UriInfoImpl(mockMessage, null);
+ // NOTE: All end with slashes (imagine they are folders)
+ assertEquals("http://example.com/app/root/a/b/c/", u.getRequestUri()
+ .toString());
+ URI absolute = URI.create("http://example.com/otherapp/fred.txt");
+
+ assertEquals("../../../../../otherapp/fred.txt", u.relativize(absolute)
+ .toString());
+
+ URI relativeToBase = URI.create("../../otherapp/fred.txt");
+ assertEquals("../../../../../otherapp/fred.txt",
+ u.relativize(relativeToBase).toString());
+ }
+
+ @Test
public void testResolveNormalizeComplex() throws Exception {
UriInfoImpl u = new UriInfoImpl(mockMessage("http://localhost:8080/baz/1/2/3/", null), null);
assertEquals("Wrong base path", "http://localhost:8080/baz/1/2/3/",
Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/HttpUtilsTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/HttpUtilsTest.java?rev=1477686&r1=1477685&r2=1477686&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/HttpUtilsTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/HttpUtilsTest.java Tue Apr 30 15:23:40 2013
@@ -45,6 +45,17 @@ public class HttpUtilsTest extends Asser
}
@Test
+ public void testRelativize() throws Exception {
+ // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6226081
+ URI a = new URI("file:/c:/abc/def/myDocument/doc.xml");
+ URI b = new URI("file:/c:/abc/def/images/subdir/image.png");
+
+ URI c = HttpUtils.relativize(a, b);
+
+ assertEquals("../images/subdir/image.png", c.toString());
+ }
+
+ @Test
public void testIsDateHeader() {
assertFalse(HttpUtils.isDateRelatedHeader(HttpHeaders.ETAG));
assertTrue(HttpUtils.isDateRelatedHeader(HttpHeaders.EXPIRES));