RFC 3986 conformance: re-use URIBuilder new functionality in URIUtils#normalizeSyntax

This commit is contained in:
Oleg Kalnichevski 2021-02-06 13:26:05 +01:00
parent 004bc85934
commit af3a7526d2
2 changed files with 9 additions and 35 deletions

View File

@ -32,9 +32,9 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Stack;
import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.URIScheme;
import org.apache.hc.core5.net.URIAuthority; import org.apache.hc.core5.net.URIAuthority;
import org.apache.hc.core5.net.URIBuilder; import org.apache.hc.core5.net.URIBuilder;
import org.apache.hc.core5.util.Args; import org.apache.hc.core5.util.Args;
@ -190,8 +190,7 @@ public class URIUtils {
} }
/** /**
* Removes dot segments according to RFC 3986, section 5.2.4 and * Removes dot segments and performs Syntax-Based Normalization.
* Syntax-Based Normalization according to RFC 3986, section 6.2.2.
* *
* @param uri the original URI * @param uri the original URI
* @return the URI without dot segments * @return the URI without dot segments
@ -201,39 +200,14 @@ public class URIUtils {
// opaque and file: URIs // opaque and file: URIs
return uri; return uri;
} }
Args.check(uri.isAbsolute(), "Base URI must be absolute");
final URIBuilder builder = new URIBuilder(uri); final URIBuilder builder = new URIBuilder(uri);
if (!builder.isPathEmpty()) { builder.normalizeSyntax();
final List<String> inputSegments = builder.getPathSegments(); if (builder.getScheme() == null) {
final Stack<String> outputSegments = new Stack<>(); builder.setScheme(URIScheme.HTTP.id);
for (final String inputSegment : inputSegments) {
if (!inputSegment.isEmpty() && !".".equals(inputSegment)) {
if ("..".equals(inputSegment)) {
if (!outputSegments.isEmpty()) {
outputSegments.pop();
}
} else {
outputSegments.push(inputSegment);
}
}
}
if (!inputSegments.isEmpty()) {
final String lastSegment = inputSegments.get(inputSegments.size() - 1);
if (lastSegment.isEmpty()) {
outputSegments.push("");
}
}
builder.setPathSegments(outputSegments);
} }
if (builder.isPathEmpty()) { if (builder.isPathEmpty()) {
builder.setPathSegments(""); builder.setPathSegments("");
} }
if (builder.getScheme() != null) {
builder.setScheme(builder.getScheme().toLowerCase(Locale.ROOT));
}
if (builder.getHost() != null) {
builder.setHost(builder.getHost().toLowerCase(Locale.ROOT));
}
return builder.build(); return builder.build();
} }

View File

@ -163,13 +163,13 @@ public class TestURIUtils {
.toString()); .toString());
Assert.assertEquals("http://a/b/c/y", URIUtils.resolve(this.baseURI, "g;x=1/../y") Assert.assertEquals("http://a/b/c/y", URIUtils.resolve(this.baseURI, "g;x=1/../y")
.toString()); .toString());
Assert.assertEquals("http://a/b/c/g?y/./x", URIUtils.resolve(this.baseURI, "g?y/./x") Assert.assertEquals("http://a/b/c/g?y%2F.%2Fx", URIUtils.resolve(this.baseURI, "g?y/./x")
.toString()); .toString());
Assert.assertEquals("http://a/b/c/g?y/../x", URIUtils.resolve(this.baseURI, "g?y/../x") Assert.assertEquals("http://a/b/c/g?y%2F..%2Fx", URIUtils.resolve(this.baseURI, "g?y/../x")
.toString()); .toString());
Assert.assertEquals("http://a/b/c/g#s/./x", URIUtils.resolve(this.baseURI, "g#s/./x") Assert.assertEquals("http://a/b/c/g#s%2F.%2Fx", URIUtils.resolve(this.baseURI, "g#s/./x")
.toString()); .toString());
Assert.assertEquals("http://a/b/c/g#s/../x", URIUtils.resolve(this.baseURI, "g#s/../x") Assert.assertEquals("http://a/b/c/g#s%2F..%2Fx", URIUtils.resolve(this.baseURI, "g#s/../x")
.toString()); .toString());
Assert.assertEquals("http:g", URIUtils.resolve(this.baseURI, "http:g").toString()); Assert.assertEquals("http:g", URIUtils.resolve(this.baseURI, "http:g").toString());
// examples from section 5.2.4 // examples from section 5.2.4