Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit fa3aee6

Browse filesBrowse files
author
adriancole
committed
issue OpenFeign#55: support iterable query params
1 parent 328fdb5 commit fa3aee6
Copy full SHA for fa3aee6

File tree

Expand file treeCollapse file tree

4 files changed

+63
-22
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

4 files changed

+63
-22
lines changed
Open diff view settings
Collapse file

‎CHANGES.md‎

Copy file name to clipboardExpand all lines: CHANGES.md
+1Lines changed: 1 addition & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
### Version 4.4
22
* Support overriding default HostnameVerifier
33
* Support GZIP content encoding for request bodies
4+
* Support Iterable args for query parameters
45

56
### Version 4.3
67
* Add ability to configure zero or more RequestInterceptors.
Collapse file

‎core/src/main/java/feign/RequestTemplate.java‎

Copy file name to clipboardExpand all lines: core/src/main/java/feign/RequestTemplate.java
+10-3Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,11 @@ public RequestTemplate(RequestTemplate toCopy) {
8484
* just the URL
8585
*/
8686
public RequestTemplate resolve(Map<String, ?> unencoded) {
87+
replaceQueryValues(unencoded);
8788
Map<String, String> encoded = new LinkedHashMap<String, String>();
8889
for (Entry<String, ?> entry : unencoded.entrySet()) {
8990
encoded.put(entry.getKey(), urlEncode(String.valueOf(entry.getValue())));
9091
}
91-
replaceQueryValues(encoded);
9292
String resolvedUrl = expand(url.toString(), encoded).replace("%2F", "/");
9393
url = new StringBuilder(resolvedUrl);
9494

@@ -509,8 +509,15 @@ public void replaceQueryValues(Map<String, ?> unencoded) {
509509
if (value.indexOf('{') == 0 && value.indexOf('}') == value.length() - 1) {
510510
Object variableValue = unencoded.get(value.substring(1, value.length() - 1));
511511
// only add non-null expressions
512-
if (variableValue != null) {
513-
values.add(String.valueOf(variableValue));
512+
if (variableValue == null) {
513+
continue;
514+
}
515+
if (variableValue instanceof Iterable) {
516+
for (Object val : Iterable.class.cast(variableValue)) {
517+
values.add(urlEncode(String.valueOf(val)));
518+
}
519+
} else {
520+
values.add(urlEncode(String.valueOf(variableValue)));
514521
}
515522
} else {
516523
values.add(value);
Collapse file

‎core/src/test/java/feign/FeignTest.java‎

Copy file name to clipboardExpand all lines: core/src/test/java/feign/FeignTest.java
+36-19Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ void login(
9191

9292
@RequestLine("GET /{1}/{2}") Response uriParam(@Named("1") String one, URI endpoint, @Named("2") String two);
9393

94+
@RequestLine("GET /?1={1}&2={2}") Response queryParams(@Named("1") String one, @Named("2") Iterable<String> twos);
95+
9496
@RequestLine("POST /") Observable<Void> observableVoid();
9597

9698
@RequestLine("POST /") Observable<String> observableString();
@@ -114,14 +116,29 @@ static class Module {
114116
}
115117
};
116118
}
119+
}
120+
}
121+
122+
@Test
123+
public void iterableQueryParams() throws IOException, InterruptedException {
124+
final MockWebServer server = new MockWebServer();
125+
server.enqueue(new MockResponse().setBody("foo"));
126+
server.play();
127+
128+
try {
129+
TestInterface api = Feign.create(TestInterface.class, "http://localhost:" + server.getPort(), new TestInterface.Module());
117130

131+
api.queryParams("user", Arrays.asList("apple", "pear"));
132+
assertEquals(server.takeRequest().getRequestLine(), "GET /?1=user&2=apple&2=pear HTTP/1.1");
133+
} finally {
134+
server.shutdown();
118135
}
119136
}
120137

121138
@Test
122139
public void observableVoid() throws IOException, InterruptedException {
123140
final MockWebServer server = new MockWebServer();
124-
server.enqueue(new MockResponse().setResponseCode(200).setBody("foo"));
141+
server.enqueue(new MockResponse().setBody("foo"));
125142
server.play();
126143

127144
try {
@@ -156,7 +173,7 @@ public void observableVoid() throws IOException, InterruptedException {
156173
@Test
157174
public void observableResponse() throws IOException, InterruptedException {
158175
final MockWebServer server = new MockWebServer();
159-
server.enqueue(new MockResponse().setResponseCode(200).setBody("foo"));
176+
server.enqueue(new MockResponse().setBody("foo"));
160177
server.play();
161178

162179
try {
@@ -202,7 +219,7 @@ static class RunSynchronous {
202219
@Test
203220
public void incrementString() throws IOException, InterruptedException {
204221
final MockWebServer server = new MockWebServer();
205-
server.enqueue(new MockResponse().setResponseCode(200).setBody("foo"));
222+
server.enqueue(new MockResponse().setBody("foo"));
206223
server.play();
207224

208225
try {
@@ -237,8 +254,8 @@ public void incrementString() throws IOException, InterruptedException {
237254
@Test
238255
public void multipleObservers() throws IOException, InterruptedException {
239256
final MockWebServer server = new MockWebServer();
240-
server.enqueue(new MockResponse().setResponseCode(200).setBody("foo"));
241-
server.enqueue(new MockResponse().setResponseCode(200).setBody("foo"));
257+
server.enqueue(new MockResponse().setBody("foo"));
258+
server.enqueue(new MockResponse().setBody("foo"));
242259
server.play();
243260

244261
try {
@@ -275,7 +292,7 @@ public void multipleObservers() throws IOException, InterruptedException {
275292
@Test
276293
public void postTemplateParamsResolve() throws IOException, InterruptedException {
277294
final MockWebServer server = new MockWebServer();
278-
server.enqueue(new MockResponse().setResponseCode(200).setBody("foo"));
295+
server.enqueue(new MockResponse().setBody("foo"));
279296
server.play();
280297

281298
try {
@@ -292,7 +309,7 @@ public void postTemplateParamsResolve() throws IOException, InterruptedException
292309
@Test
293310
public void postFormParams() throws IOException, InterruptedException {
294311
final MockWebServer server = new MockWebServer();
295-
server.enqueue(new MockResponse().setResponseCode(200).setBody("foo"));
312+
server.enqueue(new MockResponse().setBody("foo"));
296313
server.play();
297314

298315
try {
@@ -309,7 +326,7 @@ public void postFormParams() throws IOException, InterruptedException {
309326
@Test
310327
public void postBodyParam() throws IOException, InterruptedException {
311328
final MockWebServer server = new MockWebServer();
312-
server.enqueue(new MockResponse().setResponseCode(200).setBody("foo"));
329+
server.enqueue(new MockResponse().setBody("foo"));
313330
server.play();
314331

315332
try {
@@ -327,7 +344,7 @@ public void postBodyParam() throws IOException, InterruptedException {
327344
@Test
328345
public void postGZIPEncodedBodyParam() throws IOException, InterruptedException {
329346
final MockWebServer server = new MockWebServer();
330-
server.enqueue(new MockResponse().setResponseCode(200).setBody("foo"));
347+
server.enqueue(new MockResponse().setBody("foo"));
331348
server.play();
332349

333350
try {
@@ -359,7 +376,7 @@ static class ForwardedForInterceptor implements RequestInterceptor {
359376
@Test
360377
public void singleInterceptor() throws IOException, InterruptedException {
361378
final MockWebServer server = new MockWebServer();
362-
server.enqueue(new MockResponse().setResponseCode(200).setBody("foo"));
379+
server.enqueue(new MockResponse().setBody("foo"));
363380
server.play();
364381

365382
try {
@@ -387,7 +404,7 @@ static class UserAgentInterceptor implements RequestInterceptor {
387404
@Test
388405
public void multipleInterceptor() throws IOException, InterruptedException {
389406
final MockWebServer server = new MockWebServer();
390-
server.enqueue(new MockResponse().setResponseCode(200).setBody("foo"));
407+
server.enqueue(new MockResponse().setBody("foo"));
391408
server.play();
392409

393410
try {
@@ -445,7 +462,7 @@ public void canOverrideErrorDecoder() throws IOException, InterruptedException {
445462
@Test public void retriesLostConnectionBeforeRead() throws IOException, InterruptedException {
446463
MockWebServer server = new MockWebServer();
447464
server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.DISCONNECT_AT_START));
448-
server.enqueue(new MockResponse().setResponseCode(200).setBody("success!".getBytes()));
465+
server.enqueue(new MockResponse().setBody("success!".getBytes()));
449466
server.play();
450467

451468
try {
@@ -474,7 +491,7 @@ public String decode(Reader reader, Type type) throws IOException {
474491

475492
public void overrideTypeSpecificDecoder() throws IOException, InterruptedException {
476493
MockWebServer server = new MockWebServer();
477-
server.enqueue(new MockResponse().setResponseCode(200).setBody("success!".getBytes()));
494+
server.enqueue(new MockResponse().setBody("success!".getBytes()));
478495
server.play();
479496

480497
try {
@@ -508,8 +525,8 @@ public String decode(Reader reader, Type type) throws RetryableException, IOExce
508525
*/
509526
public void retryableExceptionInDecoder() throws IOException, InterruptedException {
510527
MockWebServer server = new MockWebServer();
511-
server.enqueue(new MockResponse().setResponseCode(200).setBody("retry!".getBytes()));
512-
server.enqueue(new MockResponse().setResponseCode(200).setBody("success!".getBytes()));
528+
server.enqueue(new MockResponse().setBody("retry!".getBytes()));
529+
server.enqueue(new MockResponse().setBody("success!".getBytes()));
513530
server.play();
514531

515532
try {
@@ -538,7 +555,7 @@ public String decode(Reader reader, Type type) throws IOException {
538555
@Test(expectedExceptions = FeignException.class, expectedExceptionsMessageRegExp = "error reading response POST http://.*")
539556
public void doesntRetryAfterResponseIsSent() throws IOException, InterruptedException {
540557
MockWebServer server = new MockWebServer();
541-
server.enqueue(new MockResponse().setResponseCode(200).setBody("success!".getBytes()));
558+
server.enqueue(new MockResponse().setBody("success!".getBytes()));
542559
server.play();
543560

544561
try {
@@ -562,7 +579,7 @@ static class TrustSSLSockets {
562579
@Test public void canOverrideSSLSocketFactory() throws IOException, InterruptedException {
563580
MockWebServer server = new MockWebServer();
564581
server.useHttps(TrustingSSLSocketFactory.get("localhost"), false);
565-
server.enqueue(new MockResponse().setResponseCode(200).setBody("success!".getBytes()));
582+
server.enqueue(new MockResponse().setBody("success!".getBytes()));
566583
server.play();
567584

568585
try {
@@ -584,7 +601,7 @@ static class DisableHostnameVerification {
584601
@Test public void canOverrideHostnameVerifier() throws IOException, InterruptedException {
585602
MockWebServer server = new MockWebServer();
586603
server.useHttps(TrustingSSLSocketFactory.get("bad.example.com"), false);
587-
server.enqueue(new MockResponse().setResponseCode(200).setBody("success!".getBytes()));
604+
server.enqueue(new MockResponse().setBody("success!".getBytes()));
588605
server.play();
589606

590607
try {
@@ -600,7 +617,7 @@ static class DisableHostnameVerification {
600617
MockWebServer server = new MockWebServer();
601618
server.useHttps(TrustingSSLSocketFactory.get("localhost"), false);
602619
server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.FAIL_HANDSHAKE));
603-
server.enqueue(new MockResponse().setResponseCode(200).setBody("success!".getBytes()));
620+
server.enqueue(new MockResponse().setBody("success!".getBytes()));
604621
server.play();
605622

606623
try {
Collapse file

‎core/src/test/java/feign/RequestTemplateTest.java‎

Copy file name to clipboardExpand all lines: core/src/test/java/feign/RequestTemplateTest.java
+16Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import com.google.common.collect.ImmutableMap;
2121
import org.testng.annotations.Test;
2222

23+
import java.util.Arrays;
24+
2325
import static feign.RequestTemplate.expand;
2426
import static org.testng.Assert.assertEquals;
2527

@@ -83,6 +85,20 @@ public class RequestTemplateTest {
8385
+ "GET https://iam.amazonaws.com/?Action=DescribeRegions&RegionName.1=eu-west-1 HTTP/1.1\n");
8486
}
8587

88+
@Test public void resolveTemplateWithBaseAndParameterizedIterableQuery() {
89+
RequestTemplate template = new RequestTemplate().method("GET")
90+
.append("/?Query=one").query("Queries", "{queries}");
91+
92+
template.resolve(ImmutableMap.of("queries", Arrays.asList("us-east-1", "eu-west-1")));
93+
assertEquals(template.queries(),
94+
ImmutableListMultimap.<String, String> builder()
95+
.put("Query", "one")
96+
.putAll("Queries", "us-east-1", "eu-west-1")
97+
.build().asMap());
98+
99+
assertEquals(template.toString(), "GET /?Query=one&Queries=us-east-1&Queries=eu-west-1 HTTP/1.1\n");
100+
}
101+
86102
@Test public void resolveTemplateWithMixedRequestLineParams() throws Exception {
87103
RequestTemplate template = new RequestTemplate().method("GET")//
88104
.append("/domains/{domainId}/records")//

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.