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}