From 64795664b2ce928c3c86367a88b7a4eebac84491 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Tue, 10 May 2022 11:13:54 +0100 Subject: [PATCH] Add ClientHttpResponseDecorator See gh-28190 --- .../client/ClientHttpResponseDecorator.java | 84 +++++++++++++++++++ .../client/HttpMessageConverterExtractor.java | 4 +- ...a => IntrospectingClientHttpResponse.java} | 42 ++-------- ...IntrospectingClientHttpResponseTests.java} | 12 +-- 4 files changed, 99 insertions(+), 43 deletions(-) create mode 100644 spring-web/src/main/java/org/springframework/web/client/ClientHttpResponseDecorator.java rename spring-web/src/main/java/org/springframework/web/client/{MessageBodyClientHttpResponseWrapper.java => IntrospectingClientHttpResponse.java} (78%) rename spring-web/src/test/java/org/springframework/web/client/{MessageBodyClientHttpResponseWrapperTests.java => IntrospectingClientHttpResponseTests.java} (76%) diff --git a/spring-web/src/main/java/org/springframework/web/client/ClientHttpResponseDecorator.java b/spring-web/src/main/java/org/springframework/web/client/ClientHttpResponseDecorator.java new file mode 100644 index 00000000000..3f79664487d --- /dev/null +++ b/spring-web/src/main/java/org/springframework/web/client/ClientHttpResponseDecorator.java @@ -0,0 +1,84 @@ +/* + * Copyright 2002-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.web.client; + +import java.io.IOException; +import java.io.InputStream; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.util.Assert; + + +/** + * Wrap and delegate to an existing {@link ClientHttpResponse}. + * + * @author Rossen Stoyanchev + * @since 6.0 + */ +class ClientHttpResponseDecorator implements ClientHttpResponse { + + private final ClientHttpResponse delegate; + + + public ClientHttpResponseDecorator(ClientHttpResponse delegate) { + Assert.notNull(delegate, "ClientHttpResponse delegate is required"); + this.delegate = delegate; + } + + + /** + * Return the wrapped response. + */ + public ClientHttpResponse getDelegate() { + return this.delegate; + } + + + @Override + public HttpStatusCode getStatusCode() throws IOException { + return this.delegate.getStatusCode(); + } + + @SuppressWarnings("deprecation") + @Override + public int getRawStatusCode() throws IOException { + return this.delegate.getRawStatusCode(); + } + + @Override + public String getStatusText() throws IOException { + return this.delegate.getStatusText(); + } + + @Override + public HttpHeaders getHeaders() { + return this.delegate.getHeaders(); + } + + @Override + public InputStream getBody() throws IOException { + return this.delegate.getBody(); + } + + @Override + public void close() { + this.delegate.close(); + } + +} diff --git a/spring-web/src/main/java/org/springframework/web/client/HttpMessageConverterExtractor.java b/spring-web/src/main/java/org/springframework/web/client/HttpMessageConverterExtractor.java index 246270ac876..cbc47a27287 100644 --- a/spring-web/src/main/java/org/springframework/web/client/HttpMessageConverterExtractor.java +++ b/spring-web/src/main/java/org/springframework/web/client/HttpMessageConverterExtractor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -86,7 +86,7 @@ public HttpMessageConverterExtractor(Type responseType, ListRFC 7230 Section 3.3.3 */ -class MessageBodyClientHttpResponseWrapper implements ClientHttpResponse { - - private final ClientHttpResponse response; +class IntrospectingClientHttpResponse extends ClientHttpResponseDecorator { @Nullable private PushbackInputStream pushbackInputStream; - public MessageBodyClientHttpResponseWrapper(ClientHttpResponse response) { - this.response = response; + public IntrospectingClientHttpResponse(ClientHttpResponse response) { + super(response); } @@ -82,7 +80,7 @@ public boolean hasMessageBody() throws IOException { */ @SuppressWarnings("ConstantConditions") public boolean hasEmptyMessageBody() throws IOException { - InputStream body = this.response.getBody(); + InputStream body = getDelegate().getBody(); // Per contract body shouldn't be null, but check anyway.. if (body == null) { return true; @@ -111,35 +109,9 @@ public boolean hasEmptyMessageBody() throws IOException { } - @Override - public HttpHeaders getHeaders() { - return this.response.getHeaders(); - } - @Override public InputStream getBody() throws IOException { - return (this.pushbackInputStream != null ? this.pushbackInputStream : this.response.getBody()); - } - - @Override - public HttpStatusCode getStatusCode() throws IOException { - return this.response.getStatusCode(); - } - - @Override - @Deprecated - public int getRawStatusCode() throws IOException { - return this.response.getRawStatusCode(); - } - - @Override - public String getStatusText() throws IOException { - return this.response.getStatusText(); - } - - @Override - public void close() { - this.response.close(); + return (this.pushbackInputStream != null ? this.pushbackInputStream : getDelegate().getBody()); } } diff --git a/spring-web/src/test/java/org/springframework/web/client/MessageBodyClientHttpResponseWrapperTests.java b/spring-web/src/test/java/org/springframework/web/client/IntrospectingClientHttpResponseTests.java similarity index 76% rename from spring-web/src/test/java/org/springframework/web/client/MessageBodyClientHttpResponseWrapperTests.java rename to spring-web/src/test/java/org/springframework/web/client/IntrospectingClientHttpResponseTests.java index 19568910672..dbf39cc8dce 100644 --- a/spring-web/src/test/java/org/springframework/web/client/MessageBodyClientHttpResponseWrapperTests.java +++ b/spring-web/src/test/java/org/springframework/web/client/IntrospectingClientHttpResponseTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,29 +28,29 @@ import static org.mockito.Mockito.mock; /** - * Unit tests for {@link MessageBodyClientHttpResponseWrapper}. + * Unit tests for {@link IntrospectingClientHttpResponse}. * * @since 5.3.10 * @author Yin-Jui Liao */ -class MessageBodyClientHttpResponseWrapperTests { +class IntrospectingClientHttpResponseTests { private final ClientHttpResponse response = mock(ClientHttpResponse.class); - private final MessageBodyClientHttpResponseWrapper responseWrapper = new MessageBodyClientHttpResponseWrapper(response); + private final IntrospectingClientHttpResponse wrappedResponse = new IntrospectingClientHttpResponse(response); @Test void messageBodyDoesNotExist() throws Exception { given(response.getBody()).willReturn(null); - assertThat(responseWrapper.hasEmptyMessageBody()).isTrue(); + assertThat(wrappedResponse.hasEmptyMessageBody()).isTrue(); } @Test void messageBodyExists() throws Exception { InputStream stream = new ByteArrayInputStream("content".getBytes()); given(response.getBody()).willReturn(stream); - assertThat(responseWrapper.hasEmptyMessageBody()).isFalse(); + assertThat(wrappedResponse.hasEmptyMessageBody()).isFalse(); } }