Browse Source

SpringMvcContract: Ignore RequestMapping headers with no value.

According to:

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestMapping.html#headers--

the `headers` field can take several formats:

1. Require the header with a concrete value: `"My-Header=myValue"`
2. Require the header with any value: `"My-Header"`
3. Require the header is absent: `"!My-Header"`
4. Require the header with a negated value : `"My-Header!=myValue"`

This fixes `parseHeaders` for cases 2-4 (which previously threw a `StringIndexOutOfBoundsException`).

Fixes gh-1778.
pull/6/head
Matt Bray 7 years ago
parent
commit
527dc2cc48
  1. 4
      spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/support/SpringMvcContract.java
  2. 17
      spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/support/SpringMvcContractTests.java

4
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/support/SpringMvcContract.java

@ -275,8 +275,10 @@ public class SpringMvcContract extends Contract.BaseContract
if (annotation.headers() != null && annotation.headers().length > 0) { if (annotation.headers() != null && annotation.headers().length > 0) {
for (String header : annotation.headers()) { for (String header : annotation.headers()) {
int index = header.indexOf('='); int index = header.indexOf('=');
md.template().header(resolve(header.substring(0, index)), if (!header.contains("!=") && index >= 0) {
md.template().header(resolve(header.substring(0, index)),
resolve(header.substring(index + 1).trim())); resolve(header.substring(index + 1).trim()));
}
} }
} }
} }

17
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/support/SpringMvcContractTests.java

@ -332,6 +332,18 @@ public class SpringMvcContractTests {
assertEquals("bar", data.template().headers().get("X-Foo").iterator().next()); assertEquals("bar", data.template().headers().get("X-Foo").iterator().next());
} }
@Test
public void testProcessHeadersWithoutValues() throws Exception {
Method method = TestTemplate_HeadersWithoutValues.class.getDeclaredMethod("getTest",
String.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/test/{id}", data.template().url());
assertEquals("GET", data.template().method());
assertEquals(true, data.template().headers().isEmpty());
}
@Test @Test
public void testProcessAnnotations_Fallback() throws Exception { public void testProcessAnnotations_Fallback() throws Exception {
Method method = TestTemplate_Advanced.class.getDeclaredMethod("getTestFallback", Method method = TestTemplate_Advanced.class.getDeclaredMethod("getTestFallback",
@ -462,6 +474,11 @@ public class SpringMvcContractTests {
ResponseEntity<TestObject> getTest(@PathVariable("id") String id); ResponseEntity<TestObject> getTest(@PathVariable("id") String id);
} }
public interface TestTemplate_HeadersWithoutValues {
@RequestMapping(value = "/test/{id}", method = RequestMethod.GET, headers = { "X-Foo", "!X-Bar", "X-Baz!=fooBar" })
ResponseEntity<TestObject> getTest(@PathVariable("id") String id);
}
public interface TestTemplate_ListParams { public interface TestTemplate_ListParams {
@RequestMapping(value = "/test", method = RequestMethod.GET) @RequestMapping(value = "/test", method = RequestMethod.GET)
ResponseEntity<TestObject> getTest(@RequestParam("id") List<String> id); ResponseEntity<TestObject> getTest(@RequestParam("id") List<String> id);

Loading…
Cancel
Save