Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions core/src/main/java/feign/RequestTemplate.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import feign.template.UriTemplate;
import feign.template.UriUtils;
import java.io.Serializable;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.*;
Expand Down Expand Up @@ -399,7 +400,8 @@ public RequestTemplate uri(String uri, boolean append) {

if (uri == null) {
uri = "/";
} else if ((!uri.isEmpty() && !uri.startsWith("/") && !uri.startsWith("{"))) {
} else if ((!uri.isEmpty() && !uri.startsWith("/") && !uri.startsWith("{")
&& !uri.startsWith("?"))) {
/* if the start of the url is a literal, it must begin with a slash. */
uri = "/" + uri;
}
Expand Down Expand Up @@ -447,20 +449,23 @@ public RequestTemplate target(String target) {
if (target.endsWith("/")) {
target = target.substring(0, target.length() - 1);
}

/* no query strings allowed */
Matcher queryStringMatcher = QUERY_STRING_PATTERN.matcher(target);
if (queryStringMatcher.find()) {
/*
* target has a query string, we need to make sure that they are recorded as queries
*/
int queryStart = queryStringMatcher.start();
this.extractQueryTemplates(target.substring(queryStart + 1), true);
try {
/* parse the target */
URI targetUri = URI.create(target);

if (Util.isNotBlank(targetUri.getRawQuery())) {
/*
* target has a query string, we need to make sure that they are recorded as queries
*/
this.extractQueryTemplates(targetUri.getRawQuery(), true);
}

/* strip the query string */
target = target.substring(0, queryStart);
this.target = targetUri.getScheme() + "://" + targetUri.getAuthority() + targetUri.getPath();
} catch (IllegalArgumentException iae) {
/* the uri provided is not a valid one, we can't continue */
throw new IllegalArgumentException("Target is not a valid URI.", iae);
}
this.target = target;
return this;
}

Expand Down
3 changes: 2 additions & 1 deletion core/src/test/java/feign/FeignTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,8 @@ public void ensureRetryerClonesItself() throws Exception {
.errorDecoder(new ErrorDecoder() {
@Override
public Exception decode(String methodKey, Response response) {
return new RetryableException(response.status(), "play it again sam!", HttpMethod.POST, null);
return new RetryableException(response.status(), "play it again sam!", HttpMethod.POST,
null);
}
}).target(TestInterface.class, "http://localhost:" + server.getPort());

Expand Down
2 changes: 1 addition & 1 deletion core/src/test/java/feign/LoggerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ public Retryer clone() {
return this;
}
})
.target(SendsStuff.class, "http://sna%fu.abc");
.target(SendsStuff.class, "http://sna%25fu.abc");

thrown.expect(FeignException.class);

Expand Down
42 changes: 40 additions & 2 deletions core/src/test/java/feign/TargetTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
*/
package feign;

import static feign.assertj.MockWebServerAssertions.assertThat;
import feign.Target.HardCodedTarget;
import java.net.URI;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import org.junit.Rule;
import org.junit.Test;
import feign.Target.HardCodedTarget;
import static feign.assertj.MockWebServerAssertions.assertThat;

public class TargetTest {

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

assertThat(server.takeRequest()).hasPath("/default/slash/foo?query=slash/bar");
}

interface UriTarget {

@RequestLine("GET")
Response get(URI uri);
}

@Test
public void emptyTarget() throws InterruptedException {
server.enqueue(new MockResponse());

UriTarget uriTarget = Feign.builder()
.target(Target.EmptyTarget.create(UriTarget.class));

String host = server.getHostName();
int port = server.getPort();

uriTarget.get(URI.create("http://" + host + ":" + port + "/path?query=param"));

assertThat(server.takeRequest()).hasPath("/path?query=param").hasQueryParams("query=param");
}

@Test
public void hardCodedTargetWithURI() throws InterruptedException {
server.enqueue(new MockResponse());

String host = server.getHostName();
int port = server.getPort();
String base = "http://" + host + ":" + port;

UriTarget uriTarget = Feign.builder()
.target(UriTarget.class, base);

uriTarget.get(URI.create("http://" + host + ":" + port + "/path?query=param"));

assertThat(server.takeRequest()).hasPath("/path?query=param").hasQueryParams("query=param");
}
}