001/*
002 * Copyright 2002-2019 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.web.reactive.function.client.support;
018
019import java.util.List;
020import java.util.Optional;
021import java.util.OptionalLong;
022
023import reactor.core.publisher.Flux;
024import reactor.core.publisher.Mono;
025
026import org.springframework.core.ParameterizedTypeReference;
027import org.springframework.http.HttpHeaders;
028import org.springframework.http.HttpStatus;
029import org.springframework.http.MediaType;
030import org.springframework.http.ResponseCookie;
031import org.springframework.http.ResponseEntity;
032import org.springframework.http.client.reactive.ClientHttpResponse;
033import org.springframework.util.Assert;
034import org.springframework.util.MultiValueMap;
035import org.springframework.web.reactive.function.BodyExtractor;
036import org.springframework.web.reactive.function.client.ClientResponse;
037import org.springframework.web.reactive.function.client.ExchangeStrategies;
038import org.springframework.web.reactive.function.client.WebClientResponseException;
039
040/**
041 * Implementation of the {@link ClientResponse} interface that can be subclassed
042 * to adapt the request in a
043 * {@link org.springframework.web.reactive.function.client.ExchangeFilterFunction exchange filter function}.
044 * All methods default to calling through to the wrapped request.
045 *
046 * @author Arjen Poutsma
047 * @since 5.0.5
048 */
049public class ClientResponseWrapper implements ClientResponse {
050
051        private final ClientResponse delegate;
052
053
054        /**
055         * Create a new {@code ClientResponseWrapper} that wraps the given response.
056         * @param delegate the response to wrap
057         */
058        public ClientResponseWrapper(ClientResponse delegate) {
059                Assert.notNull(delegate, "Delegate is required");
060                this.delegate = delegate;
061        }
062
063
064        /**
065         * Return the wrapped request.
066         */
067        public ClientResponse response() {
068                return this.delegate;
069        }
070
071        @Override
072        public ExchangeStrategies strategies() {
073                return this.delegate.strategies();
074        }
075
076        @Override
077        public HttpStatus statusCode() {
078                return this.delegate.statusCode();
079        }
080
081        @Override
082        public int rawStatusCode() {
083                return this.delegate.rawStatusCode();
084        }
085
086        @Override
087        public Headers headers() {
088                return this.delegate.headers();
089        }
090
091        @Override
092        public MultiValueMap<String, ResponseCookie> cookies() {
093                return this.delegate.cookies();
094        }
095
096        @Override
097        public <T> T body(BodyExtractor<T, ? super ClientHttpResponse> extractor) {
098                return this.delegate.body(extractor);
099        }
100
101        @Override
102        public <T> Mono<T> bodyToMono(Class<? extends T> elementClass) {
103                return this.delegate.bodyToMono(elementClass);
104        }
105
106        @Override
107        public <T> Mono<T> bodyToMono(ParameterizedTypeReference<T> elementTypeRef) {
108                return this.delegate.bodyToMono(elementTypeRef);
109        }
110
111        @Override
112        public <T> Flux<T> bodyToFlux(Class<? extends T> elementClass) {
113                return this.delegate.bodyToFlux(elementClass);
114        }
115
116        @Override
117        public <T> Flux<T> bodyToFlux(ParameterizedTypeReference<T> elementTypeRef) {
118                return this.delegate.bodyToFlux(elementTypeRef);
119        }
120
121        @Override
122        public Mono<Void> releaseBody() {
123                return this.delegate.releaseBody();
124        }
125
126        @Override
127        public Mono<ResponseEntity<Void>> toBodilessEntity() {
128                return this.delegate.toBodilessEntity();
129        }
130
131        @Override
132        public <T> Mono<ResponseEntity<T>> toEntity(Class<T> bodyType) {
133                return this.delegate.toEntity(bodyType);
134        }
135
136        @Override
137        public <T> Mono<ResponseEntity<T>> toEntity(ParameterizedTypeReference<T> bodyTypeReference) {
138                return this.delegate.toEntity(bodyTypeReference);
139        }
140
141        @Override
142        public <T> Mono<ResponseEntity<List<T>>> toEntityList(Class<T> elementClass) {
143                return this.delegate.toEntityList(elementClass);
144        }
145
146        @Override
147        public <T> Mono<ResponseEntity<List<T>>> toEntityList(ParameterizedTypeReference<T> elementTypeRef) {
148                return this.delegate.toEntityList(elementTypeRef);
149        }
150
151        @Override
152        public Mono<WebClientResponseException> createException() {
153                return this.delegate.createException();
154        }
155
156        @Override
157        public String logPrefix() {
158                return this.delegate.logPrefix();
159        }
160
161        /**
162         * Implementation of the {@code Headers} interface that can be subclassed
163          * to adapt the headers in a
164          * {@link org.springframework.web.reactive.function.client.ExchangeFilterFunction exchange filter function}.
165          * All methods default to calling through to the wrapped request.
166         */
167        public static class HeadersWrapper implements ClientResponse.Headers {
168
169                private final Headers headers;
170
171
172                /**
173                 * Create a new {@code HeadersWrapper} that wraps the given request.
174                 * @param headers the headers to wrap
175                 */
176                public HeadersWrapper(Headers headers) {
177                        this.headers = headers;
178                }
179
180
181                @Override
182                public OptionalLong contentLength() {
183                        return this.headers.contentLength();
184                }
185
186                @Override
187                public Optional<MediaType> contentType() {
188                        return this.headers.contentType();
189                }
190
191                @Override
192                public List<String> header(String headerName) {
193                        return this.headers.header(headerName);
194                }
195
196                @Override
197                public HttpHeaders asHttpHeaders() {
198                        return this.headers.asHttpHeaders();
199                }
200        }
201
202}