Allow interceptors to add existing header values
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
This commit is contained in:
parent
ac00d8a215
commit
554662ebab
|
@ -21,6 +21,7 @@ import java.lang.reflect.Type;
|
|||
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;
|
||||
|
@ -909,7 +910,9 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
|||
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);
|
||||
|
|
|
@ -39,12 +39,15 @@ import org.springframework.http.MediaType;
|
|||
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;
|
||||
|
@ -822,4 +825,30 @@ public class RestTemplateTests {
|
|||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue