Added QueryStringDecoder.rawPath() and rawQuery()

Motivation:

Before this commit, it is impossible to access the path component of the
URI before it has been decoded.  This makes it impossible to distinguish
between the following URIs:

/user/title?key=value
/user%2Ftitle?key=value

The user could already access the raw uri value, but they had to calculate
pathEndIdx themselves, even though it might already be cached inside
QueryStringDecoder.

Result:

The user can easily and efficiently access the undecoded path and query.
This commit is contained in:
Ned Twigg 2017-10-22 22:18:24 -07:00 committed by Norman Maurer
parent baf273aea8
commit dcbbae7f90
2 changed files with 39 additions and 0 deletions

View File

@ -182,6 +182,21 @@ public class QueryStringDecoder {
return params; return params;
} }
/**
* Returns the raw path string of the URI.
*/
public String rawPath() {
return uri.substring(0, pathEndIdx());
}
/**
* Returns raw query string of the URI.
*/
public String rawQuery() {
int start = pathEndIdx() + 1;
return start < uri.length() ? uri.substring(start) : EMPTY_STRING;
}
private int pathEndIdx() { private int pathEndIdx() {
if (pathEndIdx == -1) { if (pathEndIdx == -1) {
pathEndIdx = findPathEndIndex(uri); pathEndIdx = findPathEndIndex(uri);

View File

@ -237,6 +237,8 @@ public class QueryStringDecoderTest {
URI uri = URI.create("http://localhost:8080/foo?param1=value1&param2=value2&param3=value3"); URI uri = URI.create("http://localhost:8080/foo?param1=value1&param2=value2&param3=value3");
QueryStringDecoder decoder = new QueryStringDecoder(uri); QueryStringDecoder decoder = new QueryStringDecoder(uri);
Assert.assertEquals("/foo", decoder.path()); Assert.assertEquals("/foo", decoder.path());
Assert.assertEquals("/foo", decoder.rawPath());
Assert.assertEquals("param1=value1&param2=value2&param3=value3", decoder.rawQuery());
Map<String, List<String>> params = decoder.parameters(); Map<String, List<String>> params = decoder.parameters();
Assert.assertEquals(3, params.size()); Assert.assertEquals(3, params.size());
Iterator<Entry<String, List<String>>> entries = params.entrySet().iterator(); Iterator<Entry<String, List<String>>> entries = params.entrySet().iterator();
@ -265,6 +267,9 @@ public class QueryStringDecoderTest {
URI uri = URI.create("http://localhost:8080/?param1=value1&param2=value2&param3=value3"); URI uri = URI.create("http://localhost:8080/?param1=value1&param2=value2&param3=value3");
QueryStringDecoder decoder = new QueryStringDecoder(uri); QueryStringDecoder decoder = new QueryStringDecoder(uri);
Assert.assertEquals("/", decoder.path()); Assert.assertEquals("/", decoder.path());
Assert.assertEquals("/", decoder.rawPath());
Assert.assertEquals("param1=value1&param2=value2&param3=value3", decoder.rawQuery());
Map<String, List<String>> params = decoder.parameters(); Map<String, List<String>> params = decoder.parameters();
Assert.assertEquals(3, params.size()); Assert.assertEquals(3, params.size());
Iterator<Entry<String, List<String>>> entries = params.entrySet().iterator(); Iterator<Entry<String, List<String>>> entries = params.entrySet().iterator();
@ -293,6 +298,9 @@ public class QueryStringDecoderTest {
URI uri = URI.create("http://localhost:8080?param1=value1&param2=value2&param3=value3"); URI uri = URI.create("http://localhost:8080?param1=value1&param2=value2&param3=value3");
QueryStringDecoder decoder = new QueryStringDecoder(uri); QueryStringDecoder decoder = new QueryStringDecoder(uri);
Assert.assertEquals("", decoder.path()); Assert.assertEquals("", decoder.path());
Assert.assertEquals("", decoder.rawPath());
Assert.assertEquals("param1=value1&param2=value2&param3=value3", decoder.rawQuery());
Map<String, List<String>> params = decoder.parameters(); Map<String, List<String>> params = decoder.parameters();
Assert.assertEquals(3, params.size()); Assert.assertEquals(3, params.size());
Iterator<Entry<String, List<String>>> entries = params.entrySet().iterator(); Iterator<Entry<String, List<String>>> entries = params.entrySet().iterator();
@ -321,6 +329,9 @@ public class QueryStringDecoderTest {
URI uri = URI.create("http://foo.com/images;num=10?query=name;value=123"); URI uri = URI.create("http://foo.com/images;num=10?query=name;value=123");
QueryStringDecoder decoder = new QueryStringDecoder(uri); QueryStringDecoder decoder = new QueryStringDecoder(uri);
Assert.assertEquals("/images;num=10", decoder.path()); Assert.assertEquals("/images;num=10", decoder.path());
Assert.assertEquals("/images;num=10", decoder.rawPath());
Assert.assertEquals("query=name;value=123", decoder.rawQuery());
Map<String, List<String>> params = decoder.parameters(); Map<String, List<String>> params = decoder.parameters();
Assert.assertEquals(2, params.size()); Assert.assertEquals(2, params.size());
Iterator<Entry<String, List<String>>> entries = params.entrySet().iterator(); Iterator<Entry<String, List<String>>> entries = params.entrySet().iterator();
@ -337,4 +348,17 @@ public class QueryStringDecoderTest {
Assert.assertFalse(entries.hasNext()); Assert.assertFalse(entries.hasNext());
} }
@Test
public void testEmptyStrings() {
QueryStringDecoder pathSlash = new QueryStringDecoder("path/");
Assert.assertEquals("path/", pathSlash.rawPath());
Assert.assertEquals("", pathSlash.rawQuery());
QueryStringDecoder pathQuestion = new QueryStringDecoder("path?");
Assert.assertEquals("path", pathQuestion.rawPath());
Assert.assertEquals("", pathQuestion.rawQuery());
QueryStringDecoder empty = new QueryStringDecoder("");
Assert.assertEquals("", empty.rawPath());
Assert.assertEquals("", empty.rawQuery());
}
} }