Skip to content

Commit 989fbd7

Browse files
Carter Kozakkdavisk6
authored andcommitted
fix OpenFeign#797 fix OpenFeign#798: JAXRSContract sets a single Content-Type value (OpenFeign#799)
Closes OpenFeign#797 Closes OpenFeign#798 JAXRSContract sets a single Content-Type value This change allows headers to be cleared by passing a null value for backwards compatibility. Multiple Content-Type values are not valid because the body that we send with any given request will only have a single type. Updated header entry assertion to be agnostic to header name order. * RequestTemplate.headers clear behavior matches that of query params
1 parent 02d9737 commit 989fbd7

File tree

6 files changed

+18
-10
lines changed

6 files changed

+18
-10
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,11 @@ public RequestTemplate header(String name, Iterable<String> values) {
663663
* @return a RequestTemplate for chaining.
664664
*/
665665
private RequestTemplate appendHeader(String name, Iterable<String> values) {
666+
if (!values.iterator().hasNext()) {
667+
/* empty value, clear the existing values */
668+
this.headers.remove(name);
669+
return this;
670+
}
666671
this.headers.compute(name, (headerName, headerTemplate) -> {
667672
if (headerTemplate == null) {
668673
return HeaderTemplate.create(headerName, values);

core/src/test/java/feign/assertj/RequestTemplateAssert.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public RequestTemplateAssert hasQueries(MapEntry... entries) {
8585

8686
public RequestTemplateAssert hasHeaders(MapEntry... entries) {
8787
isNotNull();
88-
maps.assertContainsExactly(info, actual.headers(), entries);
88+
maps.assertContainsOnly(info, actual.headers(), entries);
8989
return this;
9090
}
9191

jaxrs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Appends the value to `Target.url()`. Can have tokens corresponding to `@PathPar
2323
#### `@Produces`
2424
Adds all values into the `Accept` header.
2525
#### `@Consumes`
26-
Adds all values into the `Content-Type` header.
26+
Adds the first value as the `Content-Type` header.
2727
### Parameter Annotations
2828
#### `@PathParam`
2929
Links the value of the corresponding parameter to a template variable declared in the path.

jaxrs/src/main/java/feign/jaxrs/JAXRSContract.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@
2020
import java.lang.annotation.Annotation;
2121
import java.lang.reflect.Method;
2222
import java.util.ArrayList;
23+
import java.util.Arrays;
2324
import java.util.Collection;
25+
import java.util.Collections;
26+
2427
import static feign.Util.checkState;
2528
import static feign.Util.emptyToNull;
2629
import static feign.Util.removeValues;
@@ -107,16 +110,16 @@ private void handleProducesAnnotation(MethodMetadata data, Produces produces, St
107110
String[] serverProduces =
108111
removeValues(produces.value(), (mediaType) -> emptyToNull(mediaType) == null, String.class);
109112
checkState(serverProduces.length > 0, "Produces.value() was empty on %s", name);
110-
data.template().header(ACCEPT, (String) null); // remove any previous produces
113+
data.template().header(ACCEPT, Collections.emptyList()); // remove any previous produces
111114
data.template().header(ACCEPT, serverProduces);
112115
}
113116

114117
private void handleConsumesAnnotation(MethodMetadata data, Consumes consumes, String name) {
115118
String[] serverConsumes =
116119
removeValues(consumes.value(), (mediaType) -> emptyToNull(mediaType) == null, String.class);
117120
checkState(serverConsumes.length > 0, "Consumes.value() was empty on %s", name);
118-
data.template().header(CONTENT_TYPE, (String) null); // remove any previous consumes
119-
data.template().header(CONTENT_TYPE, serverConsumes);
121+
data.template().header(CONTENT_TYPE, Collections.emptyList()); // remove any previous consumes
122+
data.template().header(CONTENT_TYPE, serverConsumes[0]);
120123
}
121124

122125
/**

jaxrs/src/test/java/feign/jaxrs/JAXRSContractTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ public void producesAddsAcceptHeader() throws Exception {
120120
assertThat(md.template())
121121
.hasHeaders(
122122
entry("Content-Type", asList("application/json")),
123-
entry("Accept", asList("application/xml", "text/html")));
123+
entry("Accept", asList("application/xml")));
124124
}
125125

126126
@Test
@@ -130,7 +130,7 @@ public void producesMultipleAddsAcceptHeader() throws Exception {
130130
assertThat(md.template())
131131
.hasHeaders(
132132
entry("Content-Type", Collections.singletonList("application/json")),
133-
entry("Accept", asList("application/xml", "text/html", "text/plain")));
133+
entry("Accept", asList("application/xml", "text/plain")));
134134
}
135135

136136
@Test
@@ -156,7 +156,7 @@ public void consumesAddsContentTypeHeader() throws Exception {
156156
/* multiple @Consumes annotations are additive */
157157
assertThat(md.template())
158158
.hasHeaders(
159-
entry("Content-Type", asList("application/xml", "application/json")),
159+
entry("Content-Type", asList("application/xml")),
160160
entry("Accept", asList("text/html")));
161161
}
162162

@@ -165,7 +165,7 @@ public void consumesMultipleAddsContentTypeHeader() throws Exception {
165165
MethodMetadata md = parseAndValidateMetadata(ProducesAndConsumes.class, "consumesMultiple");
166166

167167
assertThat(md.template())
168-
.hasHeaders(entry("Content-Type", asList("application/xml", "application/json")),
168+
.hasHeaders(entry("Content-Type", asList("application/xml")),
169169
entry("Accept", Collections.singletonList("text/html")));
170170
}
171171

jaxrs2/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Sets the request method.
2323
#### `@Path`
2424
Appends the value to `Target.url()`. Can have tokens corresponding to `@PathParam` annotations.
2525
#### `@Produces`
26-
Adds the first value as the `Accept` header.
26+
Adds all values into the `Accept` header.
2727
#### `@Consumes`
2828
Adds the first value as the `Content-Type` header.
2929
### Parameter Annotations

0 commit comments

Comments
 (0)