[java-shib-shared] 02/02: Add some additional query string methods to URISupport.
Brent Putman
putmanb at georgetown.edu
Fri Mar 21 20:26:19 UTC 2025
This is an automated email from the git hooks/post-receive script.
putmanb pushed a commit to branch maint-9.1
in repository java-shib-shared.
View the commit online:
http://git.shibboleth.net/view/?p=java-shib-shared.git;a=commit;h=b7f61d12d2ea4276f26e6ab45433783cbf3641f8
commit b7f61d12d2ea4276f26e6ab45433783cbf3641f8
Author: Brent Putman <putmanb at georgetown.edu>
AuthorDate: Fri Mar 21 16:22:39 2025 -0400
Add some additional query string methods to URISupport.
---
.../java/net/shibboleth/shared/net/URISupport.java | 54 +++++++++++++++-
.../net/shibboleth/shared/net/URISupportTest.java | 74 ++++++++++++++++++++++
2 files changed, 125 insertions(+), 3 deletions(-)
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/net/URISupport.java b/shib-networking/src/main/java/net/shibboleth/shared/net/URISupport.java
index 99389832..04ddac3e 100644
--- a/shib-networking/src/main/java/net/shibboleth/shared/net/URISupport.java
+++ b/shib-networking/src/main/java/net/shibboleth/shared/net/URISupport.java
@@ -24,6 +24,8 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -294,6 +296,33 @@ public final class URISupport {
return null;
}
+
+ /**
+ * Get all raw (i.e.RFC-3968 encoded) query string components with the specified parameter name. This method
+ * assumes the common query string format of one or more 'paramName=paramValue' pairs separated by '&'.
+ * Parameters without values will be represented in the returned map as a key associated with
+ * the value <code>null</code>.
+ *
+ * The parameter name match will be performed using the URL decoded forms of both the specified
+ * <code>paramName</code> and the candidate query string value.
+ *
+ * @param queryString the URL encoded HTTP URL query string
+ * @param paramName the URL decoded name of the parameter to find
+ * @return the found component, or null if query string or param name is null/empty or the parameter is not found
+ */
+ @Nonnull @Live public static List<Pair<String, String>> getRawQueryStringParameters(
+ @Nullable final String queryString,
+ @Nullable final String paramName) {
+
+ final String paramNameTrimmed = StringSupport.trimOrNull(paramName);
+ if (paramNameTrimmed == null) {
+ return CollectionSupport.emptyList();
+ }
+
+ return parseQueryString(queryString, false, false).stream()
+ .filter(p -> Objects.equals(doURLDecode(paramNameTrimmed), doURLDecode(p.getFirst())))
+ .collect(CollectionSupport.nonnullCollector(Collectors.toList())).get();
+ }
/**
* Parses a RFC-3968 encoded query string in to a set of name/value pairs. This method assumes the common query
@@ -305,7 +334,25 @@ public final class URISupport {
*
* @return the parameters from the query string, never null
*/
- @Nonnull @Live public static List<Pair<String, String>> parseQueryString(final String queryString) {
+ @Nonnull @Live public static List<Pair<String, String>> parseQueryString(@Nullable final String queryString) {
+ return parseQueryString(queryString, true, true);
+ }
+
+ /**
+ * Parses a RFC-3968 encoded query string in to a set of name/value pairs. This method assumes the common query
+ * string format of one or more 'paramName=paramValue' pairs separate by '&'. URL decoding of parameter names and values
+ * is determined by the relevant arguments. Parameters without values will be represented in the returned map as a key associated with
+ * the value <code>null</code>.
+ *
+ * @param queryString URL encoded query string
+ * @param decodeName whether the parameter names should be URL decoded in the returned list
+ * @param decodeValue whether the parameter values should be URL decoded in the returned list
+ *
+ * @return the parameters from the query string, never null
+ */
+ @Nonnull @Live public static List<Pair<String, String>> parseQueryString(@Nullable final String queryString,
+ final boolean decodeName, final boolean decodeValue) {
+
final String trimmedQuery = trimOrNullQuery(queryString);
if (trimmedQuery == null) {
return new LazyList<>();
@@ -317,9 +364,10 @@ public final class URISupport {
for (final String paramPair : paramPairs) {
param = paramPair.split("=");
if (param.length == 1) {
- queryParams.add(new Pair<>(doURLDecode(param[0]), (String) null));
+ queryParams.add(new Pair<>(decodeName ? doURLDecode(param[0]) : param[0], (String) null));
} else {
- queryParams.add(new Pair<>(doURLDecode(param[0]), doURLDecode(param[1])));
+ queryParams.add(new Pair<>(decodeName ? doURLDecode(param[0]) : param[0],
+ decodeValue ? doURLDecode(param[1]) : param[1]));
}
}
diff --git a/shib-networking/src/test/java/net/shibboleth/shared/net/URISupportTest.java b/shib-networking/src/test/java/net/shibboleth/shared/net/URISupportTest.java
index f1486f9c..90fdc099 100644
--- a/shib-networking/src/test/java/net/shibboleth/shared/net/URISupportTest.java
+++ b/shib-networking/src/test/java/net/shibboleth/shared/net/URISupportTest.java
@@ -244,4 +244,78 @@ public class URISupportTest {
Assert.assertTrue(params.contains(new Pair<>("paramName=", "paramValue&")));
Assert.assertTrue(params.contains(new Pair<>("paramName2", null)));
}
+
+ @Test public void testParseQueryStringWithArgs() {
+ List<Pair<String, String>> params = URISupport.parseQueryString(null, false, false);
+ Assert.assertTrue(params.isEmpty());
+
+ params = URISupport.parseQueryString("");
+ Assert.assertTrue(params.isEmpty());
+
+ String queryString = "paramName1=paramValue1¶mName%3D=paramValue%26¶mName%32";
+ params = URISupport.parseQueryString(queryString, false, false);
+ Assert.assertTrue(params.contains(new Pair<>("paramName1", "paramValue1")));
+ Assert.assertTrue(params.contains(new Pair<>("paramName%3D", "paramValue%26")));
+ Assert.assertTrue(params.contains(new Pair<>("paramName%32", null)));
+
+ queryString = "paramName1=paramValue1¶mName%3D=paramValue%26¶mName%32";
+ params = URISupport.parseQueryString(queryString, true, false);
+ Assert.assertTrue(params.contains(new Pair<>("paramName1", "paramValue1")));
+ Assert.assertTrue(params.contains(new Pair<>("paramName=", "paramValue%26")));
+ Assert.assertTrue(params.contains(new Pair<>("paramName2", null)));
+
+ queryString = "paramName1=paramValue1¶mName%3D=paramValue%26¶mName%32";
+ params = URISupport.parseQueryString(queryString, false, true);
+ Assert.assertTrue(params.contains(new Pair<>("paramName1", "paramValue1")));
+ Assert.assertTrue(params.contains(new Pair<>("paramName%3D", "paramValue&")));
+ Assert.assertTrue(params.contains(new Pair<>("paramName%32", null)));
+
+ queryString = "paramName1=paramValue1¶mName%3D=paramValue%26¶mName%32";
+ params = URISupport.parseQueryString(queryString, true, true);
+ Assert.assertTrue(params.contains(new Pair<>("paramName1", "paramValue1")));
+ Assert.assertTrue(params.contains(new Pair<>("paramName=", "paramValue&")));
+ Assert.assertTrue(params.contains(new Pair<>("paramName2", null)));
+
+ queryString = "?paramName1=paramValue1¶mName%3D=paramValue%26¶mName%32#";
+ params = URISupport.parseQueryString(queryString, true, true);
+ Assert.assertTrue(params.contains(new Pair<>("paramName1", "paramValue1")));
+ Assert.assertTrue(params.contains(new Pair<>("paramName=", "paramValue&")));
+ Assert.assertTrue(params.contains(new Pair<>("paramName2", null)));
+ }
+
+ @Test public void testGetRawQueryStringParameters() {
+ List<Pair<String, String>> params = URISupport.getRawQueryStringParameters(null, "Foo");
+ Assert.assertTrue(params.isEmpty());
+
+ params = URISupport.getRawQueryStringParameters("", "Foo");
+ Assert.assertTrue(params.isEmpty());
+
+ params = URISupport.getRawQueryStringParameters("Foo=123", "");
+ Assert.assertTrue(params.isEmpty());
+
+ String queryString = "XXX=blah&Foo=123&Foo=456&XXX=blah&Foo=789";
+ params = URISupport.getRawQueryStringParameters(queryString, "Foo");
+ Assert.assertTrue(params.contains(new Pair<>("Foo", "123")));
+ Assert.assertTrue(params.contains(new Pair<>("Foo", "456")));
+ Assert.assertTrue(params.contains(new Pair<>("Foo", "789")));
+
+ queryString = "XXX=blah&Foo=123&Foo=456&XXX=blah&Foo=789";
+ params = URISupport.getRawQueryStringParameters(queryString, "F%6F%6F");
+ Assert.assertTrue(params.contains(new Pair<>("Foo", "123")));
+ Assert.assertTrue(params.contains(new Pair<>("Foo", "456")));
+ Assert.assertTrue(params.contains(new Pair<>("Foo", "789")));
+
+ queryString = "XXX=blah&F%6Fo=1%323&F%6F%6F=4%356&XXX=blah&Fo%6F=7%389";
+ params = URISupport.getRawQueryStringParameters(queryString, "Foo");
+ Assert.assertTrue(params.contains(new Pair<>("F%6Fo", "1%323")));
+ Assert.assertTrue(params.contains(new Pair<>("F%6F%6F", "4%356")));
+ Assert.assertTrue(params.contains(new Pair<>("Fo%6F", "7%389")));
+
+ queryString = "XXX=blah&F%6Fo=1%323&F%6F%6F=4%356&XXX=blah&Fo%6F=7%389";
+ params = URISupport.getRawQueryStringParameters(queryString, "F%6F%6F");
+ Assert.assertTrue(params.contains(new Pair<>("F%6Fo", "1%323")));
+ Assert.assertTrue(params.contains(new Pair<>("F%6F%6F", "4%356")));
+ Assert.assertTrue(params.contains(new Pair<>("Fo%6F", "7%389")));
+ }
+
}
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list