Skip to content

Commit ef3e038

Browse files
authored
No Longer prepend uri with slash if it is a query string (#889)
* No Longer prepend uri with slash if it is a query string Fixes #887 Changes to target and uri parsing did not take into account Empty Targets or URI provided methods. In these scenarios, the target contains the entire path and the uri will be the query string only. This change takes that into account and no longer prepends a slash in these cases. * Removed unnecessary import for Spring from Target Test
1 parent f821a93 commit ef3e038

File tree

3 files changed

+58
-15
lines changed

3 files changed

+58
-15
lines changed

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

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import feign.template.UriTemplate;
2020
import feign.template.UriUtils;
2121
import java.io.Serializable;
22+
import java.net.URI;
2223
import java.nio.charset.Charset;
2324
import java.util.AbstractMap.SimpleImmutableEntry;
2425
import java.util.*;
@@ -399,7 +400,8 @@ public RequestTemplate uri(String uri, boolean append) {
399400

400401
if (uri == null) {
401402
uri = "/";
402-
} else if ((!uri.isEmpty() && !uri.startsWith("/") && !uri.startsWith("{"))) {
403+
} else if ((!uri.isEmpty() && !uri.startsWith("/") && !uri.startsWith("{")
404+
&& !uri.startsWith("?"))) {
403405
/* if the start of the url is a literal, it must begin with a slash. */
404406
uri = "/" + uri;
405407
}
@@ -447,20 +449,23 @@ public RequestTemplate target(String target) {
447449
if (target.endsWith("/")) {
448450
target = target.substring(0, target.length() - 1);
449451
}
450-
451-
/* no query strings allowed */
452-
Matcher queryStringMatcher = QUERY_STRING_PATTERN.matcher(target);
453-
if (queryStringMatcher.find()) {
454-
/*
455-
* target has a query string, we need to make sure that they are recorded as queries
456-
*/
457-
int queryStart = queryStringMatcher.start();
458-
this.extractQueryTemplates(target.substring(queryStart + 1), true);
452+
try {
453+
/* parse the target */
454+
URI targetUri = URI.create(target);
455+
456+
if (Util.isNotBlank(targetUri.getRawQuery())) {
457+
/*
458+
* target has a query string, we need to make sure that they are recorded as queries
459+
*/
460+
this.extractQueryTemplates(targetUri.getRawQuery(), true);
461+
}
459462

460463
/* strip the query string */
461-
target = target.substring(0, queryStart);
464+
this.target = targetUri.getScheme() + "://" + targetUri.getAuthority() + targetUri.getPath();
465+
} catch (IllegalArgumentException iae) {
466+
/* the uri provided is not a valid one, we can't continue */
467+
throw new IllegalArgumentException("Target is not a valid URI.", iae);
462468
}
463-
this.target = target;
464469
return this;
465470
}
466471

core/src/test/java/feign/LoggerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ public Retryer clone() {
318318
return this;
319319
}
320320
})
321-
.target(SendsStuff.class, "http://sna%fu.abc");
321+
.target(SendsStuff.class, "http://sna%25fu.abc");
322322

323323
thrown.expect(FeignException.class);
324324

core/src/test/java/feign/TargetTest.java

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@
1313
*/
1414
package feign;
1515

16+
import static feign.assertj.MockWebServerAssertions.assertThat;
17+
import feign.Target.HardCodedTarget;
18+
import java.net.URI;
1619
import okhttp3.mockwebserver.MockResponse;
1720
import okhttp3.mockwebserver.MockWebServer;
1821
import org.junit.Rule;
1922
import org.junit.Test;
20-
import feign.Target.HardCodedTarget;
21-
import static feign.assertj.MockWebServerAssertions.assertThat;
2223

2324
public class TargetTest {
2425

@@ -68,4 +69,41 @@ public Request apply(RequestTemplate input) {
6869

6970
assertThat(server.takeRequest()).hasPath("/default/slash/foo?query=slash/bar");
7071
}
72+
73+
interface UriTarget {
74+
75+
@RequestLine("GET")
76+
Response get(URI uri);
77+
}
78+
79+
@Test
80+
public void emptyTarget() throws InterruptedException {
81+
server.enqueue(new MockResponse());
82+
83+
UriTarget uriTarget = Feign.builder()
84+
.target(Target.EmptyTarget.create(UriTarget.class));
85+
86+
String host = server.getHostName();
87+
int port = server.getPort();
88+
89+
uriTarget.get(URI.create("http://" + host + ":" + port + "/path?query=param"));
90+
91+
assertThat(server.takeRequest()).hasPath("/path?query=param").hasQueryParams("query=param");
92+
}
93+
94+
@Test
95+
public void hardCodedTargetWithURI() throws InterruptedException {
96+
server.enqueue(new MockResponse());
97+
98+
String host = server.getHostName();
99+
int port = server.getPort();
100+
String base = "http://" + host + ":" + port;
101+
102+
UriTarget uriTarget = Feign.builder()
103+
.target(UriTarget.class, base);
104+
105+
uriTarget.get(URI.create("http://" + host + ":" + port + "/path?query=param"));
106+
107+
assertThat(server.takeRequest()).hasPath("/path?query=param").hasQueryParams("query=param");
108+
}
71109
}

0 commit comments

Comments
 (0)