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}