diff --git a/core/src/main/java/feign/Contract.java b/core/src/main/java/feign/Contract.java index 3cc6d128..df949e33 100644 --- a/core/src/main/java/feign/Contract.java +++ b/core/src/main/java/feign/Contract.java @@ -82,10 +82,11 @@ public interface Contract { data.returnType(Types.resolve(targetType, targetType, method.getGenericReturnType())); data.configKey(Feign.configKey(targetType, method)); - processAnnotationOnClass(data, method.getDeclaringClass()); - if (method.getDeclaringClass() != targetType) { - processAnnotationOnClass(data, targetType); + if(targetType.getInterfaces().length == 1) { + processAnnotationOnClass(data, targetType.getInterfaces()[0]); } + processAnnotationOnClass(data, targetType); + for (Annotation methodAnnotation : method.getAnnotations()) { processAnnotationOnMethod(data, methodAnnotation, method); diff --git a/core/src/test/java/feign/DefaultContractTest.java b/core/src/test/java/feign/DefaultContractTest.java index b0e3eda1..0a5bfb6b 100644 --- a/core/src/test/java/feign/DefaultContractTest.java +++ b/core/src/test/java/feign/DefaultContractTest.java @@ -528,6 +528,50 @@ public class DefaultContractTest { .isEmpty(); } + @Headers("Authorization: {authHdr}") + interface ParameterizedHeaderBase { + } + + interface ParameterizedHeaderExpandInheritedApi extends ParameterizedHeaderBase { + @RequestLine("GET /api/{zoneId}") + @Headers("Accept: application/json") + String getZoneAccept(@Param("zoneId") String vhost, @Param("authHdr") String authHdr); + + @RequestLine("GET /api/{zoneId}") + String getZone(@Param("zoneId") String vhost, @Param("authHdr") String authHdr); + } + + @Test + public void parameterizedHeaderExpandApiBaseClass() throws Exception { + List mds = contract.parseAndValidatateMetadata(ParameterizedHeaderExpandInheritedApi.class); + + Map byConfigKey = new LinkedHashMap(); + for (MethodMetadata m : mds) { + byConfigKey.put(m.configKey(), m); + } + + assertThat(byConfigKey) + .containsOnlyKeys("ParameterizedHeaderExpandInheritedApi#getZoneAccept(String,String)", + "ParameterizedHeaderExpandInheritedApi#getZone(String,String)"); + + MethodMetadata md = byConfigKey.get("ParameterizedHeaderExpandInheritedApi#getZoneAccept(String,String)"); + assertThat(md.returnType()) + .isEqualTo(String.class); + assertThat(md.template()) + .hasHeaders(entry("Authorization", asList("{authHdr}")), entry("Accept", asList("application/json"))); + // Ensure that the authHdr expansion was properly detected and did not create a formParam + assertThat(md.formParams()) + .isEmpty(); + + md = byConfigKey.get("ParameterizedHeaderExpandInheritedApi#getZone(String,String)"); + assertThat(md.returnType()) + .isEqualTo(String.class); + assertThat(md.template()) + .hasHeaders(entry("Authorization", asList("{authHdr}"))); + assertThat(md.formParams()) + .isEmpty(); + } + private MethodMetadata parseAndValidateMetadata(Class targetType, String method, Class... parameterTypes) throws NoSuchMethodException {