Skip to content

Commit

Permalink
Allow interceptors to add existing header values
Browse files Browse the repository at this point in the history
Provide a fully mutable HttpHeaders to ClientHttpRequestInterceptors
of a RestTemplate when headers are set using HttpEntity. This avoids
UnsupportedOperationException if both HttpEntity and
ClientHttpRequestInterceptor add values for the same HTTP header.

Issue: SPR-15066
  • Loading branch information
sdeleuze committed Dec 11, 2017
1 parent ac00d8a commit 554662e
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -909,7 +910,9 @@ public void doWithRequest(ClientHttpRequest httpRequest) throws IOException {
HttpHeaders httpHeaders = httpRequest.getHeaders();
HttpHeaders requestHeaders = this.requestEntity.getHeaders();
if (!requestHeaders.isEmpty()) {
httpHeaders.putAll(requestHeaders);
for (Map.Entry<String, List<String>> entry : requestHeaders.entrySet()) {
httpHeaders.put(entry.getKey(), new LinkedList<>(entry.getValue()));
}
}
if (httpHeaders.getContentLength() < 0) {
httpHeaders.setContentLength(0L);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,15 @@
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.converter.GenericHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.util.StreamUtils;
import org.springframework.web.util.DefaultUriBuilderFactory;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*;
import static org.springframework.http.HttpMethod.POST;
Expand Down Expand Up @@ -822,4 +825,30 @@ public void exchangeParameterizedType() throws Exception {
verify(response).close();
}

@Test // SPR-15066
public void requestInterceptorCanAddExistingHeaderValue() throws Exception {
ClientHttpRequestInterceptor interceptor = (request, body, execution) -> {
request.getHeaders().add("MyHeader", "MyInterceptorValue");
return execution.execute(request, body);
};
template.setInterceptors(Collections.singletonList(interceptor));

given(requestFactory.createRequest(new URI("http://example.com"), HttpMethod.POST)).willReturn(request);
HttpHeaders requestHeaders = new HttpHeaders();
given(request.getHeaders()).willReturn(requestHeaders);
given(request.execute()).willReturn(response);
given(errorHandler.hasError(response)).willReturn(false);
HttpStatus status = HttpStatus.OK;
given(response.getStatusCode()).willReturn(status);
given(response.getStatusText()).willReturn(status.getReasonPhrase());

HttpHeaders entityHeaders = new HttpHeaders();
entityHeaders.add("MyHeader", "MyEntityValue");
HttpEntity<Void> entity = new HttpEntity<>(null, entityHeaders);
template.exchange("http://example.com", HttpMethod.POST, entity, Void.class);
assertThat(requestHeaders.get("MyHeader"), contains("MyEntityValue", "MyInterceptorValue"));

verify(response).close();
}

}

0 comments on commit 554662e

Please sign in to comment.