32
32
import org .springframework .http .HttpMethod ;
33
33
import org .springframework .http .MediaType ;
34
34
import org .springframework .http .client .reactive .ClientHttpRequest ;
35
+ import org .springframework .util .CollectionUtils ;
36
+ import org .springframework .util .LinkedMultiValueMap ;
35
37
import org .springframework .util .MultiValueMap ;
36
38
import org .springframework .web .reactive .function .BodyInserter ;
37
39
import org .springframework .web .util .DefaultUriBuilderFactory ;
@@ -50,10 +52,22 @@ class DefaultWebClient implements WebClient {
50
52
51
53
private final UriBuilderFactory uriBuilderFactory ;
52
54
55
+ private final HttpHeaders defaultHeaders ;
56
+
57
+ private final MultiValueMap <String , String > defaultCookies ;
58
+
59
+
60
+ DefaultWebClient (ExchangeFunction exchangeFunction , UriBuilderFactory factory ,
61
+ HttpHeaders defaultHeaders , MultiValueMap <String , String > defaultCookies ) {
53
62
54
- DefaultWebClient (ExchangeFunction exchangeFunction , UriBuilderFactory factory ) {
55
63
this .exchangeFunction = exchangeFunction ;
56
64
this .uriBuilderFactory = (factory != null ? factory : new DefaultUriBuilderFactory ());
65
+
66
+ this .defaultHeaders = defaultHeaders != null ?
67
+ HttpHeaders .readOnlyHttpHeaders (defaultHeaders ) : null ;
68
+
69
+ this .defaultCookies = defaultCookies != null ?
70
+ CollectionUtils .unmodifiableMultiValueMap (defaultCookies ) : null ;
57
71
}
58
72
59
73
@@ -110,7 +124,8 @@ private UriSpec method(HttpMethod httpMethod) {
110
124
@ Override
111
125
public WebClient filter (ExchangeFilterFunction filterFunction ) {
112
126
ExchangeFunction filteredExchangeFunction = this .exchangeFunction .filter (filterFunction );
113
- return new DefaultWebClient (filteredExchangeFunction , this .uriBuilderFactory );
127
+ return new DefaultWebClient (filteredExchangeFunction ,
128
+ this .uriBuilderFactory , this .defaultHeaders , this .defaultCookies );
114
129
}
115
130
116
131
@@ -123,11 +138,6 @@ private class DefaultUriSpec implements UriSpec {
123
138
this .httpMethod = httpMethod ;
124
139
}
125
140
126
- @ Override
127
- public HeaderSpec uri (URI uri ) {
128
- return new DefaultHeaderSpec (ClientRequest .method (this .httpMethod , uri ));
129
- }
130
-
131
141
@ Override
132
142
public HeaderSpec uri (String uriTemplate , Object ... uriVariables ) {
133
143
return uri (getUriBuilderFactory ().expand (uriTemplate , uriVariables ));
@@ -137,103 +147,173 @@ public HeaderSpec uri(String uriTemplate, Object... uriVariables) {
137
147
public HeaderSpec uri (Function <UriBuilderFactory , URI > uriFunction ) {
138
148
return uri (uriFunction .apply (getUriBuilderFactory ()));
139
149
}
150
+
151
+ @ Override
152
+ public HeaderSpec uri (URI uri ) {
153
+ return new DefaultHeaderSpec (this .httpMethod , uri );
154
+ }
140
155
}
141
156
142
157
private class DefaultHeaderSpec implements HeaderSpec {
143
158
144
- private final ClientRequest .Builder requestBuilder ;
159
+ private final HttpMethod httpMethod ;
160
+
161
+ private final URI uri ;
145
162
146
- private final HttpHeaders headers = new HttpHeaders ();
163
+ private HttpHeaders headers ;
164
+
165
+ private MultiValueMap <String , String > cookies ;
166
+
167
+
168
+ DefaultHeaderSpec (HttpMethod httpMethod , URI uri ) {
169
+ this .httpMethod = httpMethod ;
170
+ this .uri = uri ;
171
+ }
147
172
148
173
149
- DefaultHeaderSpec (ClientRequest .Builder requestBuilder ) {
150
- this .requestBuilder = requestBuilder ;
174
+ private HttpHeaders getHeaders () {
175
+ if (this .headers == null ) {
176
+ this .headers = new HttpHeaders ();
177
+ }
178
+ return this .headers ;
151
179
}
152
180
181
+ private MultiValueMap <String , String > getCookies () {
182
+ if (this .cookies == null ) {
183
+ this .cookies = new LinkedMultiValueMap <>(4 );
184
+ }
185
+ return this .cookies ;
186
+ }
153
187
154
188
@ Override
155
189
public DefaultHeaderSpec header (String headerName , String ... headerValues ) {
156
190
for (String headerValue : headerValues ) {
157
- this . headers .add (headerName , headerValue );
191
+ getHeaders () .add (headerName , headerValue );
158
192
}
159
193
return this ;
160
194
}
161
195
162
196
@ Override
163
197
public DefaultHeaderSpec headers (HttpHeaders headers ) {
164
198
if (headers != null ) {
165
- this . headers .putAll (headers );
199
+ getHeaders () .putAll (headers );
166
200
}
167
201
return this ;
168
202
}
169
203
170
204
@ Override
171
205
public DefaultHeaderSpec accept (MediaType ... acceptableMediaTypes ) {
172
- this . headers .setAccept (Arrays .asList (acceptableMediaTypes ));
206
+ getHeaders () .setAccept (Arrays .asList (acceptableMediaTypes ));
173
207
return this ;
174
208
}
175
209
176
210
@ Override
177
211
public DefaultHeaderSpec acceptCharset (Charset ... acceptableCharsets ) {
178
- this . headers .setAcceptCharset (Arrays .asList (acceptableCharsets ));
212
+ getHeaders () .setAcceptCharset (Arrays .asList (acceptableCharsets ));
179
213
return this ;
180
214
}
181
215
182
216
@ Override
183
217
public DefaultHeaderSpec contentType (MediaType contentType ) {
184
- this . headers .setContentType (contentType );
218
+ getHeaders () .setContentType (contentType );
185
219
return this ;
186
220
}
187
221
188
222
@ Override
189
223
public DefaultHeaderSpec contentLength (long contentLength ) {
190
- this . headers .setContentLength (contentLength );
224
+ getHeaders () .setContentLength (contentLength );
191
225
return this ;
192
226
}
193
227
194
228
@ Override
195
229
public DefaultHeaderSpec cookie (String name , String value ) {
196
- this . requestBuilder . cookie (name , value );
230
+ getCookies (). add (name , value );
197
231
return this ;
198
232
}
199
233
200
234
@ Override
201
235
public DefaultHeaderSpec cookies (MultiValueMap <String , String > cookies ) {
202
- this .requestBuilder .cookies (cookies );
236
+ if (cookies != null ) {
237
+ getCookies ().putAll (cookies );
238
+ }
203
239
return this ;
204
240
}
205
241
206
242
@ Override
207
243
public DefaultHeaderSpec ifModifiedSince (ZonedDateTime ifModifiedSince ) {
208
244
ZonedDateTime gmt = ifModifiedSince .withZoneSameInstant (ZoneId .of ("GMT" ));
209
245
String headerValue = DateTimeFormatter .RFC_1123_DATE_TIME .format (gmt );
210
- this . headers .set (HttpHeaders .IF_MODIFIED_SINCE , headerValue );
246
+ getHeaders () .set (HttpHeaders .IF_MODIFIED_SINCE , headerValue );
211
247
return this ;
212
248
}
213
249
214
250
@ Override
215
251
public DefaultHeaderSpec ifNoneMatch (String ... ifNoneMatches ) {
216
- this . headers .setIfNoneMatch (Arrays .asList (ifNoneMatches ));
252
+ getHeaders () .setIfNoneMatch (Arrays .asList (ifNoneMatches ));
217
253
return this ;
218
254
}
219
255
220
256
@ Override
221
257
public Mono <ClientResponse > exchange () {
222
- ClientRequest <Void > request = this . requestBuilder . headers ( this . headers ).build ();
258
+ ClientRequest <Void > request = initRequestBuilder ( ).build ();
223
259
return getExchangeFunction ().exchange (request );
224
260
}
225
261
226
262
@ Override
227
263
public <T > Mono <ClientResponse > exchange (BodyInserter <T , ? super ClientHttpRequest > inserter ) {
228
- ClientRequest <T > request = this . requestBuilder . headers ( this . headers ).body (inserter );
264
+ ClientRequest <T > request = initRequestBuilder ( ).body (inserter );
229
265
return getExchangeFunction ().exchange (request );
230
266
}
231
267
232
268
@ Override
233
269
public <T , S extends Publisher <T >> Mono <ClientResponse > exchange (S publisher , Class <T > elementClass ) {
234
- ClientRequest <S > request = this . requestBuilder .headers (this .headers ).body (publisher , elementClass );
270
+ ClientRequest <S > request = initRequestBuilder () .headers (this .headers ).body (publisher , elementClass );
235
271
return getExchangeFunction ().exchange (request );
236
272
}
273
+
274
+ private ClientRequest .Builder initRequestBuilder () {
275
+ return ClientRequest .method (this .httpMethod , this .uri ).headers (initHeaders ()).cookies (initCookies ());
276
+ }
277
+
278
+ private HttpHeaders initHeaders () {
279
+ if (CollectionUtils .isEmpty (defaultHeaders ) && CollectionUtils .isEmpty (this .headers )) {
280
+ return null ;
281
+ }
282
+ else if (CollectionUtils .isEmpty (defaultHeaders )) {
283
+ return this .headers ;
284
+ }
285
+ else if (CollectionUtils .isEmpty (this .headers )) {
286
+ return defaultHeaders ;
287
+ }
288
+ else {
289
+ HttpHeaders result = new HttpHeaders ();
290
+ result .putAll (this .headers );
291
+ defaultHeaders .forEach ((name , values ) -> {
292
+ if (!this .headers .containsKey (name )) {
293
+ values .forEach (value -> result .add (name , value ));
294
+ }
295
+ });
296
+ return result ;
297
+ }
298
+ }
299
+
300
+ private MultiValueMap <String , String > initCookies () {
301
+ if (CollectionUtils .isEmpty (defaultCookies ) && CollectionUtils .isEmpty (this .cookies )) {
302
+ return null ;
303
+ }
304
+ else if (CollectionUtils .isEmpty (defaultCookies )) {
305
+ return this .cookies ;
306
+ }
307
+ else if (CollectionUtils .isEmpty (this .cookies )) {
308
+ return defaultCookies ;
309
+ }
310
+ else {
311
+ MultiValueMap <String , String > result = new LinkedMultiValueMap <>();
312
+ result .putAll (this .cookies );
313
+ defaultCookies .forEach (result ::putIfAbsent );
314
+ return result ;
315
+ }
316
+ }
237
317
}
238
318
239
319
}
0 commit comments