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; 018 019import java.net.URI; 020import java.util.Map; 021import java.util.Optional; 022import java.util.function.Consumer; 023 024import org.reactivestreams.Publisher; 025import reactor.core.publisher.Mono; 026 027import org.springframework.core.ParameterizedTypeReference; 028import org.springframework.http.HttpHeaders; 029import org.springframework.http.HttpMethod; 030import org.springframework.http.client.reactive.ClientHttpRequest; 031import org.springframework.util.MultiValueMap; 032import org.springframework.web.reactive.function.BodyInserter; 033 034/** 035 * Represents a typed, immutable, client-side HTTP request, as executed by the 036 * {@link ExchangeFunction}. Instances of this interface can be created via static 037 * builder methods. 038 * 039 * <p>Note that applications are more likely to perform requests through 040 * {@link WebClient} rather than using this directly. 041 * 042 * @author Brian Clozel 043 * @author Arjen Poutsma 044 * @since 5.0 045 */ 046public interface ClientRequest { 047 048 /** 049 * Name of {@link #attributes() attribute} whose value can be used to 050 * correlate log messages for this request. Use {@link #logPrefix()} to 051 * obtain a consistently formatted prefix based on this attribute. 052 * @since 5.1 053 * @see #logPrefix() 054 */ 055 String LOG_ID_ATTRIBUTE = ClientRequest.class.getName() + ".LOG_ID"; 056 057 058 /** 059 * Return the HTTP method. 060 */ 061 HttpMethod method(); 062 063 /** 064 * Return the request URI. 065 */ 066 URI url(); 067 068 /** 069 * Return the headers of this request. 070 */ 071 HttpHeaders headers(); 072 073 /** 074 * Return the cookies of this request. 075 */ 076 MultiValueMap<String, String> cookies(); 077 078 /** 079 * Return the body inserter of this request. 080 */ 081 BodyInserter<?, ? super ClientHttpRequest> body(); 082 083 /** 084 * Return the request attribute value if present. 085 * @param name the attribute name 086 * @return the attribute value 087 */ 088 default Optional<Object> attribute(String name) { 089 return Optional.ofNullable(attributes().get(name)); 090 } 091 092 /** 093 * Return the attributes of this request. 094 */ 095 Map<String, Object> attributes(); 096 097 /** 098 * Return a log message prefix to use to correlate messages for this request. 099 * The prefix is based on the value of the attribute {@link #LOG_ID_ATTRIBUTE 100 * LOG_ID_ATTRIBUTE} surrounded with "[" and "]". 101 * @return the log message prefix or an empty String if the 102 * {@link #LOG_ID_ATTRIBUTE LOG_ID_ATTRIBUTE} is not set. 103 * @since 5.1 104 */ 105 String logPrefix(); 106 107 /** 108 * Write this request to the given {@link ClientHttpRequest}. 109 * @param request the client http request to write to 110 * @param strategies the strategies to use when writing 111 * @return {@code Mono<Void>} to indicate when writing is complete 112 */ 113 Mono<Void> writeTo(ClientHttpRequest request, ExchangeStrategies strategies); 114 115 116 // Static builder methods 117 118 /** 119 * Create a builder with the method, URI, headers, and cookies of the given request. 120 * @param other the request to copy the method, URI, headers, and cookies from 121 * @return the created builder 122 */ 123 static Builder from(ClientRequest other) { 124 return new DefaultClientRequestBuilder(other); 125 } 126 127 /** 128 * Create a builder with the given method and url. 129 * @param method the HTTP method (GET, POST, etc) 130 * @param url the url (as a URI instance) 131 * @return the created builder 132 * @deprecated in favor of {@link #create(HttpMethod, URI)} 133 */ 134 @Deprecated 135 static Builder method(HttpMethod method, URI url) { 136 return new DefaultClientRequestBuilder(method, url); 137 } 138 139 /** 140 * Create a request builder with the given method and url. 141 * @param method the HTTP method (GET, POST, etc) 142 * @param url the url (as a URI instance) 143 * @return the created builder 144 */ 145 static Builder create(HttpMethod method, URI url) { 146 return new DefaultClientRequestBuilder(method, url); 147 } 148 149 150 /** 151 * Defines a builder for a request. 152 */ 153 interface Builder { 154 155 /** 156 * Set the method of the request. 157 * @param method the new method 158 * @return this builder 159 * @since 5.0.1 160 */ 161 Builder method(HttpMethod method); 162 163 /** 164 * Set the url of the request. 165 * @param url the new url 166 * @return this builder 167 * @since 5.0.1 168 */ 169 Builder url(URI url); 170 171 /** 172 * Add the given header value(s) under the given name. 173 * @param headerName the header name 174 * @param headerValues the header value(s) 175 * @return this builder 176 * @see HttpHeaders#add(String, String) 177 */ 178 Builder header(String headerName, String... headerValues); 179 180 /** 181 * Manipulate this request's headers with the given consumer. The 182 * headers provided to the consumer are "live", so that the consumer can be used to 183 * {@linkplain HttpHeaders#set(String, String) overwrite} existing header values, 184 * {@linkplain HttpHeaders#remove(Object) remove} values, or use any of the other 185 * {@link HttpHeaders} methods. 186 * @param headersConsumer a function that consumes the {@code HttpHeaders} 187 * @return this builder 188 */ 189 Builder headers(Consumer<HttpHeaders> headersConsumer); 190 191 /** 192 * Add a cookie with the given name and value(s). 193 * @param name the cookie name 194 * @param values the cookie value(s) 195 * @return this builder 196 */ 197 Builder cookie(String name, String... values); 198 199 /** 200 * Manipulate this request's cookies with the given consumer. The 201 * map provided to the consumer is "live", so that the consumer can be used to 202 * {@linkplain MultiValueMap#set(Object, Object) overwrite} existing header values, 203 * {@linkplain MultiValueMap#remove(Object) remove} values, or use any of the other 204 * {@link MultiValueMap} methods. 205 * @param cookiesConsumer a function that consumes the cookies map 206 * @return this builder 207 */ 208 Builder cookies(Consumer<MultiValueMap<String, String>> cookiesConsumer); 209 210 /** 211 * Set the body of the request to the given {@code BodyInserter}. 212 * @param inserter the {@code BodyInserter} that writes to the request 213 * @return this builder 214 */ 215 Builder body(BodyInserter<?, ? super ClientHttpRequest> inserter); 216 217 /** 218 * Set the body of the request to the given {@code Publisher} and return it. 219 * @param publisher the {@code Publisher} to write to the request 220 * @param elementClass the class of elements contained in the publisher 221 * @param <S> the type of the elements contained in the publisher 222 * @param <P> the type of the {@code Publisher} 223 * @return the built request 224 */ 225 <S, P extends Publisher<S>> Builder body(P publisher, Class<S> elementClass); 226 227 /** 228 * Set the body of the request to the given {@code Publisher} and return it. 229 * @param publisher the {@code Publisher} to write to the request 230 * @param typeReference a type reference describing the elements contained in the publisher 231 * @param <S> the type of the elements contained in the publisher 232 * @param <P> the type of the {@code Publisher} 233 * @return the built request 234 */ 235 <S, P extends Publisher<S>> Builder body(P publisher, ParameterizedTypeReference<S> typeReference); 236 237 /** 238 * Set the attribute with the given name to the given value. 239 * @param name the name of the attribute to add 240 * @param value the value of the attribute to add 241 * @return this builder 242 */ 243 Builder attribute(String name, Object value); 244 245 /** 246 * Manipulate the request attributes with the given consumer. The attributes provided to 247 * the consumer are "live", so that the consumer can be used to inspect attributes, 248 * remove attributes, or use any of the other map-provided methods. 249 * @param attributesConsumer a function that consumes the attributes 250 * @return this builder 251 */ 252 Builder attributes(Consumer<Map<String, Object>> attributesConsumer); 253 254 /** 255 * Build the request. 256 */ 257 ClientRequest build(); 258 } 259 260}