From 45770824957e13766688a6af093f9073d2de5595 Mon Sep 17 00:00:00 2001 From: Jacques-Etienne Beaudet Date: Sat, 21 Feb 2015 17:50:30 +0000 Subject: [PATCH] Supports query params without values Fixes NPE when building a client with a query param with no values --- CHANGELOG.md | 1 + core/src/main/java/feign/RequestTemplate.java | 8 ++---- core/src/main/java/feign/Util.java | 2 +- .../test/java/feign/DefaultContractTest.java | 28 +++++++++++++++++-- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4a0a2a65e..dbc79a256d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Adds Request.Options support to RibbonClient * Updates to Ribbon 2.0-RC13 * Updates to Jackson 2.5.1 +* Supports query parameters without values ### Version 7.2 * Adds `Feign.Builder.build()` diff --git a/core/src/main/java/feign/RequestTemplate.java b/core/src/main/java/feign/RequestTemplate.java index 607a90b3b2..a7c7a69d2d 100644 --- a/core/src/main/java/feign/RequestTemplate.java +++ b/core/src/main/java/feign/RequestTemplate.java @@ -145,11 +145,7 @@ private static Map> parseAndDecodeQueries(String quer return map; } if (queryLine.indexOf('&') == -1) { - if (queryLine.indexOf('=') != -1) { - putKV(queryLine, map); - } else { - map.put(queryLine, null); - } + putKV(queryLine, map); } else { char[] chars = queryLine.toCharArray(); int start = 0; @@ -504,7 +500,7 @@ private StringBuilder pullAnyQueriesOutOfUrl(StringBuilder url) { } private boolean allValuesAreNull(Collection values) { - if (values.isEmpty()) { + if (values == null || values.isEmpty()) { return true; } for (String val : values) { diff --git a/core/src/main/java/feign/Util.java b/core/src/main/java/feign/Util.java index 7469c9b03f..3e044ddc0b 100644 --- a/core/src/main/java/feign/Util.java +++ b/core/src/main/java/feign/Util.java @@ -139,7 +139,7 @@ public static T[] toArray(Iterable iterable, Class type) { * Returns an unmodifiable collection which may be empty, but is never null. */ public static Collection valuesOrEmpty(Map> map, String key) { - return map.containsKey(key) ? map.get(key) : Collections.emptyList(); + return map.containsKey(key) && map.get(key) != null ? map.get(key) : Collections.emptyList(); } public static void ensureClosed(Closeable closeable) { diff --git a/core/src/test/java/feign/DefaultContractTest.java b/core/src/test/java/feign/DefaultContractTest.java index 99b1b7a727..2bfc4adc66 100644 --- a/core/src/test/java/feign/DefaultContractTest.java +++ b/core/src/test/java/feign/DefaultContractTest.java @@ -22,6 +22,7 @@ import org.junit.rules.ExpectedException; import java.net.URI; +import java.util.Collections; import java.util.Date; import java.util.List; @@ -124,7 +125,7 @@ public void queryParamsInPathExtract() throws Exception { ); assertThat( - contract.parseAndValidatateMetadata(WithQueryParamsInPath.class.getDeclaredMethod("empty")) + contract.parseAndValidatateMetadata(WithQueryParamsInPath.class.getDeclaredMethod("twoAndOneEmpty")) .template()) .hasUrl("/") .hasQueries( @@ -132,6 +133,23 @@ public void queryParamsInPathExtract() throws Exception { entry("Action", asList("GetUser")), entry("Version", asList("2010-05-08")) ); + + assertThat( + contract.parseAndValidatateMetadata(WithQueryParamsInPath.class.getDeclaredMethod("oneEmpty")) + .template()) + .hasUrl("/") + .hasQueries( + entry("flag", asList(new String[]{null})) + ); + + assertThat( + contract.parseAndValidatateMetadata(WithQueryParamsInPath.class.getDeclaredMethod("twoEmpty")) + .template()) + .hasUrl("/") + .hasQueries( + entry("flag", asList(new String[]{null})), + entry("NoErrors", asList(new String[]{null})) + ); } @Test @@ -307,7 +325,13 @@ interface WithQueryParamsInPath { Response three(); @RequestLine("GET /?flag&Action=GetUser&Version=2010-05-08") - Response empty(); + Response twoAndOneEmpty(); + + @RequestLine("GET /?flag") + Response oneEmpty(); + + @RequestLine("GET /?flag&NoErrors") + Response twoEmpty(); } interface BodyWithoutParameters {