Skip to content

Commit 5c04c96

Browse files
committed
Honor attributes configured in ServerRequest.from() builder
Prior to this commit, if attributes were configured in the builder returned by `ServerRequest.from(...)`, those attributes were not available in the `ServerRequest` built by the builder. In addition, any attributes in the original `ServerRequest` supplied to `ServerRequest.from(...)` were also ignored. This commit addresses this issue by ensuring that the attributes configured via DefaultServerRequestBuilder are used as the attributes in the resulting `ServerRequest`. This commit also polishes the Javadoc in `ServerRequest` and `ClientResponse` and avoids the use of lambda expressions in the constructors for `DefaultServerRequestBuilder` and `DefaultClientResponseBuilder`. Closes spring-projectsgh-25106
1 parent 7d39fbe commit 5c04c96

File tree

5 files changed

+67
-42
lines changed

5 files changed

+67
-42
lines changed

spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ClientResponse.java

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -82,7 +82,7 @@ public interface ClientResponse {
8282
Headers headers();
8383

8484
/**
85-
* Return cookies of this response.
85+
* Return the cookies of this response.
8686
*/
8787
MultiValueMap<String, ResponseCookie> cookies();
8888

@@ -253,7 +253,7 @@ interface Headers {
253253
List<String> header(String headerName);
254254

255255
/**
256-
* Return the headers as a {@link HttpHeaders} instance.
256+
* Return the headers as an {@link HttpHeaders} instance.
257257
*/
258258
HttpHeaders asHttpHeaders();
259259
}
@@ -266,34 +266,34 @@ interface Builder {
266266

267267
/**
268268
* Set the status code of the response.
269-
* @param statusCode the new status code.
269+
* @param statusCode the new status code
270270
* @return this builder
271271
*/
272272
Builder statusCode(HttpStatus statusCode);
273273

274274
/**
275275
* Set the raw status code of the response.
276-
* @param statusCode the new status code.
276+
* @param statusCode the new status code
277277
* @return this builder
278278
* @since 5.1.9
279279
*/
280280
Builder rawStatusCode(int statusCode);
281281

282282
/**
283283
* Add the given header value(s) under the given name.
284-
* @param headerName the header name
284+
* @param headerName the header name
285285
* @param headerValues the header value(s)
286286
* @return this builder
287287
* @see HttpHeaders#add(String, String)
288288
*/
289289
Builder header(String headerName, String... headerValues);
290290

291291
/**
292-
* Manipulate this response's headers with the given consumer. The
293-
* headers provided to the consumer are "live", so that the consumer can be used to
294-
* {@linkplain HttpHeaders#set(String, String) overwrite} existing header values,
295-
* {@linkplain HttpHeaders#remove(Object) remove} values, or use any of the other
296-
* {@link HttpHeaders} methods.
292+
* Manipulate this response's headers with the given consumer.
293+
* <p>The headers provided to the consumer are "live", so that the consumer
294+
* can be used to {@linkplain HttpHeaders#set(String, String) overwrite}
295+
* existing header values, {@linkplain HttpHeaders#remove(Object) remove}
296+
* values, or use any of the other {@link HttpHeaders} methods.
297297
* @param headersConsumer a function that consumes the {@code HttpHeaders}
298298
* @return this builder
299299
*/
@@ -308,9 +308,9 @@ interface Builder {
308308
Builder cookie(String name, String... values);
309309

310310
/**
311-
* Manipulate this response's cookies with the given consumer. The
312-
* map provided to the consumer is "live", so that the consumer can be used to
313-
* {@linkplain MultiValueMap#set(Object, Object) overwrite} existing header values,
311+
* Manipulate this response's cookies with the given consumer.
312+
* <p>The map provided to the consumer is "live", so that the consumer can be used to
313+
* {@linkplain MultiValueMap#set(Object, Object) overwrite} existing cookie values,
314314
* {@linkplain MultiValueMap#remove(Object) remove} values, or use any of the other
315315
* {@link MultiValueMap} methods.
316316
* @param cookiesConsumer a function that consumes the cookies map
@@ -319,20 +319,21 @@ interface Builder {
319319
Builder cookies(Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer);
320320

321321
/**
322-
* Set the body of the response. Calling this methods will
322+
* Set the body of the response.
323+
* <p>Calling this methods will
323324
* {@linkplain org.springframework.core.io.buffer.DataBufferUtils#release(DataBuffer) release}
324325
* the existing body of the builder.
325-
* @param body the new body.
326+
* @param body the new body
326327
* @return this builder
327328
*/
328329
Builder body(Flux<DataBuffer> body);
329330

330331
/**
331332
* Set the body of the response to the UTF-8 encoded bytes of the given string.
332-
* Calling this methods will
333+
* <p>Calling this methods will
333334
* {@linkplain org.springframework.core.io.buffer.DataBufferUtils#release(DataBuffer) release}
334335
* the existing body of the builder.
335-
* @param body the new body.
336+
* @param body the new body
336337
* @return this builder
337338
*/
338339
Builder body(String body);

spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponseBuilder.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -53,17 +53,17 @@ final class DefaultClientResponseBuilder implements ClientResponse.Builder {
5353
private Flux<DataBuffer> body = Flux.empty();
5454

5555

56-
public DefaultClientResponseBuilder(ExchangeStrategies strategies) {
56+
DefaultClientResponseBuilder(ExchangeStrategies strategies) {
5757
Assert.notNull(strategies, "ExchangeStrategies must not be null");
5858
this.strategies = strategies;
5959
}
6060

61-
public DefaultClientResponseBuilder(ClientResponse other) {
61+
DefaultClientResponseBuilder(ClientResponse other) {
6262
Assert.notNull(other, "ClientResponse must not be null");
6363
this.strategies = other.strategies();
6464
this.statusCode = other.rawStatusCode();
65-
headers(headers -> headers.addAll(other.headers().asHttpHeaders()));
66-
cookies(cookies -> cookies.addAll(other.cookies()));
65+
this.headers.addAll(other.headers().asHttpHeaders());
66+
this.cookies.addAll(other.cookies());
6767
}
6868

6969

@@ -153,7 +153,7 @@ private static class BuiltClientHttpResponse implements ClientHttpResponse {
153153

154154
private final Flux<DataBuffer> body;
155155

156-
public BuiltClientHttpResponse(int statusCode, HttpHeaders headers,
156+
BuiltClientHttpResponse(int statusCode, HttpHeaders headers,
157157
MultiValueMap<String, ResponseCookie> cookies, Flux<DataBuffer> body) {
158158

159159
this.statusCode = statusCode;

spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerRequestBuilder.java

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -63,6 +63,7 @@
6363
* Default {@link ServerRequest.Builder} implementation.
6464
*
6565
* @author Arjen Poutsma
66+
* @author Sam Brannen
6667
* @since 5.1
6768
*/
6869
class DefaultServerRequestBuilder implements ServerRequest.Builder {
@@ -84,15 +85,15 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
8485
private Flux<DataBuffer> body = Flux.empty();
8586

8687

87-
public DefaultServerRequestBuilder(ServerRequest other) {
88+
DefaultServerRequestBuilder(ServerRequest other) {
8889
Assert.notNull(other, "ServerRequest must not be null");
8990
this.messageReaders = other.messageReaders();
9091
this.exchange = other.exchange();
9192
this.methodName = other.methodName();
9293
this.uri = other.uri();
93-
headers(headers -> headers.addAll(other.headers().asHttpHeaders()));
94-
cookies(cookies -> cookies.addAll(other.cookies()));
95-
attributes(attributes -> attributes.putAll(other.attributes()));
94+
this.headers.addAll(other.headers().asHttpHeaders());
95+
this.cookies.addAll(other.cookies());
96+
this.attributes.putAll(other.attributes());
9697
}
9798

9899

@@ -180,7 +181,7 @@ public ServerRequest build() {
180181
ServerHttpRequest serverHttpRequest = new BuiltServerHttpRequest(this.exchange.getRequest().getId(),
181182
this.methodName, this.uri, this.headers, this.cookies, this.body);
182183
ServerWebExchange exchange = new DelegatingServerWebExchange(
183-
serverHttpRequest, this.exchange, this.messageReaders);
184+
serverHttpRequest, this.attributes, this.exchange, this.messageReaders);
184185
return new DefaultServerRequest(exchange, this.messageReaders);
185186
}
186187

@@ -301,16 +302,19 @@ private static class DelegatingServerWebExchange implements ServerWebExchange {
301302

302303
private final ServerHttpRequest request;
303304

305+
private final Map<String, Object> attributes;
306+
304307
private final ServerWebExchange delegate;
305308

306309
private final Mono<MultiValueMap<String, String>> formDataMono;
307310

308311
private final Mono<MultiValueMap<String, Part>> multipartDataMono;
309312

310-
public DelegatingServerWebExchange(
311-
ServerHttpRequest request, ServerWebExchange delegate, List<HttpMessageReader<?>> messageReaders) {
313+
DelegatingServerWebExchange(ServerHttpRequest request, Map<String, Object> attributes,
314+
ServerWebExchange delegate, List<HttpMessageReader<?>> messageReaders) {
312315

313316
this.request = request;
317+
this.attributes = attributes;
314318
this.delegate = delegate;
315319
this.formDataMono = initFormData(request, messageReaders);
316320
this.multipartDataMono = initMultipartData(request, messageReaders);
@@ -359,11 +363,17 @@ private static Mono<MultiValueMap<String, Part>> initMultipartData(ServerHttpReq
359363
}
360364
return EMPTY_MULTIPART_DATA;
361365
}
366+
362367
@Override
363368
public ServerHttpRequest getRequest() {
364369
return this.request;
365370
}
366371

372+
@Override
373+
public Map<String, Object> getAttributes() {
374+
return this.attributes;
375+
}
376+
367377
@Override
368378
public Mono<MultiValueMap<String, String>> getFormData() {
369379
return this.formDataMono;
@@ -381,11 +391,6 @@ public ServerHttpResponse getResponse() {
381391
return this.delegate.getResponse();
382392
}
383393

384-
@Override
385-
public Map<String, Object> getAttributes() {
386-
return this.delegate.getAttributes();
387-
}
388-
389394
@Override
390395
public Mono<WebSession> getSession() {
391396
return this.delegate.getSession();
@@ -442,4 +447,5 @@ public String getLogPrefix() {
442447
return this.delegate.getLogPrefix();
443448
}
444449
}
450+
445451
}

spring-webflux/src/main/java/org/springframework/web/reactive/function/server/ServerRequest.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -296,8 +296,10 @@ static ServerRequest create(ServerWebExchange exchange, List<HttpMessageReader<?
296296
}
297297

298298
/**
299-
* Create a builder with the status, headers, and cookies of the given request.
300-
* @param other the response to copy the status, headers, and cookies from
299+
* Create a builder with the {@linkplain HttpMessageReader message readers},
300+
* method name, URI, headers, cookies, and attributes of the given request.
301+
* @param other the request to copy the message readers, method name, URI,
302+
* headers, and attributes from
301303
* @return the created builder
302304
* @since 5.1
303305
*/
@@ -359,7 +361,7 @@ interface Headers {
359361
List<HttpRange> range();
360362

361363
/**
362-
* Get the header value(s), if any, for the header of the given name.
364+
* Get the header value(s), if any, for the header with the given name.
363365
* <p>Returns an empty list if no header values are found.
364366
* @param headerName the header name
365367
*/

spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DefaultServerRequestBuilderTests.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,6 +17,8 @@
1717
package org.springframework.web.reactive.function.server;
1818

1919
import java.nio.charset.StandardCharsets;
20+
import java.util.Arrays;
21+
import java.util.HashSet;
2022

2123
import org.junit.Test;
2224
import reactor.core.publisher.Flux;
@@ -29,11 +31,15 @@
2931
import org.springframework.http.ResponseCookie;
3032
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
3133
import org.springframework.mock.web.test.server.MockServerWebExchange;
34+
import org.springframework.web.server.ServerWebExchange;
3235

3336
import static org.junit.Assert.*;
3437

3538
/**
39+
* Unit tests for {@link DefaultServerRequestBuilder}.
40+
*
3641
* @author Arjen Poutsma
42+
* @author Sam Brannen
3743
*/
3844
public class DefaultServerRequestBuilderTests {
3945

@@ -49,6 +55,7 @@ public void from() {
4955

5056
ServerRequest other =
5157
ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders());
58+
other.attributes().put("attr1", "value1");
5259

5360
Flux<DataBuffer> body = Flux.just("baz")
5461
.map(s -> s.getBytes(StandardCharsets.UTF_8))
@@ -58,6 +65,8 @@ public void from() {
5865
.method(HttpMethod.HEAD)
5966
.headers(httpHeaders -> httpHeaders.set("foo", "baar"))
6067
.cookies(cookies -> cookies.set("baz", ResponseCookie.from("baz", "quux").build()))
68+
.attribute("attr2", "value2")
69+
.attributes(attributes -> attributes.put("attr3", "value3"))
6170
.body(body)
6271
.build();
6372

@@ -67,6 +76,13 @@ public void from() {
6776
assertEquals(1, result.cookies().size());
6877
assertEquals("quux", result.cookies().getFirst("baz").getValue());
6978

79+
assertEquals(4, result.attributes().size());
80+
assertEquals(new HashSet<>(Arrays.asList(ServerWebExchange.LOG_ID_ATTRIBUTE, "attr1", "attr2", "attr3")),
81+
result.attributes().keySet());
82+
assertEquals("value1", result.attributes().get("attr1"));
83+
assertEquals("value2", result.attributes().get("attr2"));
84+
assertEquals("value3", result.attributes().get("attr3"));
85+
7086
StepVerifier.create(result.bodyToFlux(String.class))
7187
.expectNext("baz")
7288
.verifyComplete();

0 commit comments

Comments
 (0)