Browse Source

Added possibility to leave slash encoded in path parameters

pull/243/head
unknown 10 years ago
parent
commit
e79518d037
  1. 3
      core/src/main/java/feign/Contract.java
  2. 1
      core/src/main/java/feign/RequestLine.java
  3. 18
      core/src/main/java/feign/RequestTemplate.java
  4. 26
      core/src/test/java/feign/DefaultContractTest.java
  5. 18
      core/src/test/java/feign/FeignBuilderTest.java
  6. 12
      core/src/test/java/feign/RequestTemplateTest.java

3
core/src/main/java/feign/Contract.java

@ -168,6 +168,9 @@ public interface Contract { @@ -168,6 +168,9 @@ public interface Contract {
data.template().append(
requestLine.substring(requestLine.indexOf(' ') + 1, requestLine.lastIndexOf(' ')));
}
data.template().decodeSlash(RequestLine.class.cast(methodAnnotation).decodeSlash());
} else if (annotationType == Body.class) {
String body = Body.class.cast(methodAnnotation).value();
checkState(emptyToNull(body) != null, "Body annotation was empty on method %s.",

1
core/src/main/java/feign/RequestLine.java

@ -47,4 +47,5 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; @@ -47,4 +47,5 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
public @interface RequestLine {
String value();
boolean decodeSlash() default true;
}

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

@ -58,6 +58,7 @@ public final class RequestTemplate implements Serializable { @@ -58,6 +58,7 @@ public final class RequestTemplate implements Serializable {
private transient Charset charset;
private byte[] body;
private String bodyTemplate;
private boolean decodeSlash = true;
public RequestTemplate() {
@ -73,6 +74,7 @@ public final class RequestTemplate implements Serializable { @@ -73,6 +74,7 @@ public final class RequestTemplate implements Serializable {
this.charset = toCopy.charset;
this.body = toCopy.body;
this.bodyTemplate = toCopy.bodyTemplate;
this.decodeSlash = toCopy.decodeSlash;
}
private static String urlDecode(String arg) {
@ -190,7 +192,10 @@ public final class RequestTemplate implements Serializable { @@ -190,7 +192,10 @@ public final class RequestTemplate implements Serializable {
for (Entry<String, ?> entry : unencoded.entrySet()) {
encoded.put(entry.getKey(), urlEncode(String.valueOf(entry.getValue())));
}
String resolvedUrl = expand(url.toString(), encoded).replace("%2F", "/");
String resolvedUrl = expand(url.toString(), encoded);
if (decodeSlash) {
resolvedUrl = resolvedUrl.replace("%2F", "/");
}
url = new StringBuilder(resolvedUrl);
Map<String, Collection<String>>
@ -230,12 +235,21 @@ public final class RequestTemplate implements Serializable { @@ -230,12 +235,21 @@ public final class RequestTemplate implements Serializable {
this.method = checkNotNull(method, "method");
return this;
}
/* @see Request#method() */
public String method() {
return method;
}
public RequestTemplate decodeSlash(boolean decodeSlash) {
this.decodeSlash = decodeSlash;
return this;
}
public boolean decodeSlash() {
return decodeSlash;
}
/* @see #url() */
public RequestTemplate append(CharSequence value) {
url.append(value);

26
core/src/test/java/feign/DefaultContractTest.java

@ -341,6 +341,22 @@ public class DefaultContractTest { @@ -341,6 +341,22 @@ public class DefaultContractTest {
assertThat(md.indexToName())
.containsExactly(entry(0, asList("Auth-Token")));
}
@Test
public void slashAreEncodedWhenNeeded() throws Exception {
MethodMetadata
md =
contract.parseAndValidatateMetadata(
SlashNeedToBeEncoded.class.getDeclaredMethod("getQueues", String.class));
assertThat(md.template().decodeSlash()).isFalse();
md = contract.parseAndValidatateMetadata(
SlashNeedToBeEncoded.class.getDeclaredMethod("getZone", String.class));
assertThat(md.template().decodeSlash()).isTrue();
}
interface Methods {
@ -471,7 +487,7 @@ public class DefaultContractTest { @@ -471,7 +487,7 @@ public class DefaultContractTest {
@Headers("Auth-Token: {Auth-Token}")
void logout(@Named("Auth-Token") String token);
}
class DateToMillis implements Param.Expander {
@Override
@ -479,4 +495,12 @@ public class DefaultContractTest { @@ -479,4 +495,12 @@ public class DefaultContractTest {
return String.valueOf(((Date) value).getTime());
}
}
interface SlashNeedToBeEncoded {
@RequestLine(value = "GET /api/queues/{vhost}", decodeSlash = false)
String getQueues(@Param("vhost") String vhost);
@RequestLine("GET /api/{zoneId}")
String getZone(@Param("ZoneId") String vhost);
}
}

18
core/src/test/java/feign/FeignBuilderTest.java

@ -142,6 +142,21 @@ public class FeignBuilderTest { @@ -142,6 +142,21 @@ public class FeignBuilderTest {
assertThat(server.takeRequest())
.hasBody("request data");
}
@Test
public void testSlashIsEncodedInPathParams() throws Exception {
server.enqueue(new MockResponse().setBody("response data"));
String url = "http://localhost:" + server.getPort();
TestInterface
api =
Feign.builder().target(TestInterface.class, url);
api.getQueues("/");
assertThat(server.takeRequest())
.hasPath("/api/queues/%2F");
}
interface TestInterface {
@ -153,5 +168,8 @@ public class FeignBuilderTest { @@ -153,5 +168,8 @@ public class FeignBuilderTest {
@RequestLine("POST /")
String decodedPost();
@RequestLine(value = "GET /api/queues/{vhost}", decodeSlash = false)
String getQueues(@Param("vhost") String vhost);
}
}

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

@ -230,4 +230,16 @@ public class RequestTemplateTest { @@ -230,4 +230,16 @@ public class RequestTemplateTest {
.hasUrl("/domains/1001/records")
.hasQueries();
}
@Test
public void encodeSlashTest() throws Exception {
RequestTemplate template = new RequestTemplate().method("GET")
.append("/api/{vhost}")
.decodeSlash(false);
template.resolve(mapOf("vhost", "/"));
assertThat(template)
.hasUrl("/api/%2F");
}
}

Loading…
Cancel
Save