From dcbbae7f9006f5b995d055702dd1c9f55f0e0c9d Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Sun, 22 Oct 2017 22:18:24 -0700 Subject: [PATCH] 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. --- .../codec/http/QueryStringDecoder.java | 15 ++++++++++++ .../codec/http/QueryStringDecoderTest.java | 24 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/QueryStringDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/QueryStringDecoder.java index 6a8a05da65..7c631f31ce 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/QueryStringDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/QueryStringDecoder.java @@ -182,6 +182,21 @@ public class QueryStringDecoder { 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() { if (pathEndIdx == -1) { pathEndIdx = findPathEndIndex(uri); diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/QueryStringDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/QueryStringDecoderTest.java index d0d5c1ce90..a0071c4a70 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/QueryStringDecoderTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/QueryStringDecoderTest.java @@ -237,6 +237,8 @@ public class QueryStringDecoderTest { URI uri = URI.create("http://localhost:8080/foo?param1=value1¶m2=value2¶m3=value3"); QueryStringDecoder decoder = new QueryStringDecoder(uri); Assert.assertEquals("/foo", decoder.path()); + Assert.assertEquals("/foo", decoder.rawPath()); + Assert.assertEquals("param1=value1¶m2=value2¶m3=value3", decoder.rawQuery()); Map> params = decoder.parameters(); Assert.assertEquals(3, params.size()); Iterator>> entries = params.entrySet().iterator(); @@ -265,6 +267,9 @@ public class QueryStringDecoderTest { URI uri = URI.create("http://localhost:8080/?param1=value1¶m2=value2¶m3=value3"); QueryStringDecoder decoder = new QueryStringDecoder(uri); Assert.assertEquals("/", decoder.path()); + Assert.assertEquals("/", decoder.rawPath()); + Assert.assertEquals("param1=value1¶m2=value2¶m3=value3", decoder.rawQuery()); + Map> params = decoder.parameters(); Assert.assertEquals(3, params.size()); Iterator>> entries = params.entrySet().iterator(); @@ -293,6 +298,9 @@ public class QueryStringDecoderTest { URI uri = URI.create("http://localhost:8080?param1=value1¶m2=value2¶m3=value3"); QueryStringDecoder decoder = new QueryStringDecoder(uri); Assert.assertEquals("", decoder.path()); + Assert.assertEquals("", decoder.rawPath()); + Assert.assertEquals("param1=value1¶m2=value2¶m3=value3", decoder.rawQuery()); + Map> params = decoder.parameters(); Assert.assertEquals(3, params.size()); Iterator>> 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"); QueryStringDecoder decoder = new QueryStringDecoder(uri); Assert.assertEquals("/images;num=10", decoder.path()); + Assert.assertEquals("/images;num=10", decoder.rawPath()); + Assert.assertEquals("query=name;value=123", decoder.rawQuery()); + Map> params = decoder.parameters(); Assert.assertEquals(2, params.size()); Iterator>> entries = params.entrySet().iterator(); @@ -337,4 +348,17 @@ public class QueryStringDecoderTest { 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()); + } }