Skip to content

Commit

Permalink
Ensure @Body and @param parsing consistency (#1137)
Browse files Browse the repository at this point in the history
Relates to #561 

Corrects inconsistent processing during Contract parsing with `formParams` are mixed with `@Body` parameters where order of parameters mattered, when it shouldn't.

Test Case:
```java

@RequestLine("POST /")
void formParamAndBodyParams(
        @param("customer_name") String customer,
        String body);

@RequestLine("POST /")
void bodyParamsAndformParam(
        String body,
        @param("customer_name") String customer);

```
  • Loading branch information
switchYello authored and kdavisk6 committed Dec 30, 2019
1 parent 1821d94 commit 6e64865
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 7 deletions.
18 changes: 11 additions & 7 deletions core/src/main/java/feign/Contract.java
Expand Up @@ -117,13 +117,17 @@ protected MethodMetadata parseAndValidateMetadata(Class<?> targetType, Method me

if (parameterTypes[i] == URI.class) {
data.urlIndex(i);
} else if (!isHttpAnnotation && parameterTypes[i] != Request.Options.class
&& !data.isAlreadyProcessed(i)) {
checkState(data.formParams().isEmpty(),
"Body parameters cannot be used with form parameters.");
checkState(data.bodyIndex() == null, "Method has too many Body parameters: %s", method);
data.bodyIndex(i);
data.bodyType(Types.resolve(targetType, targetType, genericParameterTypes[i]));
} else if (!isHttpAnnotation && parameterTypes[i] != Request.Options.class) {
if (data.isAlreadyProcessed(i)) {
checkState(data.formParams().isEmpty() || data.bodyIndex() == null,
"Body parameters cannot be used with form parameters.");
} else {
checkState(data.formParams().isEmpty(),
"Body parameters cannot be used with form parameters.");
checkState(data.bodyIndex() == null, "Method has too many Body parameters: %s", method);
data.bodyIndex(i);
data.bodyType(Types.resolve(targetType, targetType, genericParameterTypes[i]));
}
}
}

Expand Down
52 changes: 52 additions & 0 deletions core/src/test/java/feign/DefaultContractTest.java
Expand Up @@ -227,6 +227,42 @@ public void formParamsParseIntoIndexToName() throws Exception {
entry(2, asList("password")));
}

@Test
public void formParamAndBodyParams() throws Exception {
thrown.expect(IllegalStateException.class);
thrown.expectMessage("Body parameters cannot be used with form parameters.");

parseAndValidateMetadata(FormParams.class,
"formParamAndBodyParams", String.class, String.class);
Fail.failBecauseExceptionWasNotThrown(IllegalStateException.class);
}

@Test
public void bodyParamsAndformParam() throws Exception {
thrown.expect(IllegalStateException.class);
thrown.expectMessage("Body parameters cannot be used with form parameters.");

parseAndValidateMetadata(FormParams.class,
"bodyParamsAndformParam", String.class, String.class);
Fail.failBecauseExceptionWasNotThrown(IllegalStateException.class);
}

@Test
public void formParamParseIntoFormParams() throws Exception {

MethodMetadata md = parseAndValidateMetadata(FormParams.class,
"loginNoBodyTemplate", String.class, String.class, String.class);

assertThat(md.formParams())
.containsExactly("customer_name", "user_name", "password");

assertThat(md.indexToName()).containsExactly(
entry(0, asList("customer_name")),
entry(1, asList("user_name")),
entry(2, asList("password")));
}


/**
* Body type is only for the body param.
*/
Expand Down Expand Up @@ -490,6 +526,22 @@ void login(
@Param("customer_name") String customer,
@Param("user_name") String user,
@Param("password") String password);

@RequestLine("POST /")
void loginNoBodyTemplate(
@Param("customer_name") String customer,
@Param("user_name") String user,
@Param("password") String password);

@RequestLine("POST /")
void formParamAndBodyParams(
@Param("customer_name") String customer,
String body);

@RequestLine("POST /")
void bodyParamsAndformParam(
String body,
@Param("customer_name") String customer);
}

interface HeaderMapInterface {
Expand Down

0 comments on commit 6e64865

Please sign in to comment.