Skip to content

Commit c3f22b7

Browse files
committed
Add "mutate" builder to ServerWebExchange
This commit adds a default mutate method to ServerWebExchange which prepares an immutable wrapper and returns the provided mutated properties.
1 parent afcc120 commit c3f22b7

File tree

3 files changed

+189
-5
lines changed

3 files changed

+189
-5
lines changed
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
* Copyright 2002-2016 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.web.server;
17+
18+
import java.security.Principal;
19+
import java.util.Optional;
20+
21+
import reactor.core.publisher.Mono;
22+
23+
import org.springframework.http.server.reactive.ServerHttpRequest;
24+
import org.springframework.http.server.reactive.ServerHttpResponse;
25+
import org.springframework.util.Assert;
26+
27+
/**
28+
* Default implementation of
29+
* {@link org.springframework.web.server.ServerWebExchange.MutativeBuilder}.
30+
*
31+
* @author Rossen Stoyanchev
32+
* @since 5.0
33+
*/
34+
class DefaultServerWebExchangeMutativeBuilder implements ServerWebExchange.MutativeBuilder {
35+
36+
private final ServerWebExchange delegate;
37+
38+
private ServerHttpRequest request;
39+
40+
private ServerHttpResponse response;
41+
42+
private Principal user;
43+
44+
private Mono<WebSession> session;
45+
46+
47+
public DefaultServerWebExchangeMutativeBuilder(ServerWebExchange delegate) {
48+
Assert.notNull(delegate, "'delegate' is required.");
49+
this.delegate = delegate;
50+
}
51+
52+
53+
@Override
54+
public ServerWebExchange.MutativeBuilder setRequest(ServerHttpRequest request) {
55+
this.request = request;
56+
return this;
57+
}
58+
59+
@Override
60+
public ServerWebExchange.MutativeBuilder setResponse(ServerHttpResponse response) {
61+
this.response = response;
62+
return this;
63+
}
64+
65+
@Override
66+
public ServerWebExchange.MutativeBuilder setPrincipal(Principal user) {
67+
this.user = user;
68+
return this;
69+
}
70+
71+
@Override
72+
public ServerWebExchange.MutativeBuilder setSession(Mono<WebSession> session) {
73+
this.session = session;
74+
return this;
75+
}
76+
77+
@Override
78+
public ServerWebExchange build() {
79+
return new MutativeDecorator(this.delegate,
80+
this.request, this.response, this.user, this.session);
81+
}
82+
83+
84+
/**
85+
* An immutable wrapper of an exchange returning property overrides -- given
86+
* to the constructor -- or original values otherwise.
87+
*/
88+
private static class MutativeDecorator extends ServerWebExchangeDecorator {
89+
90+
private final ServerHttpRequest request;
91+
92+
private final ServerHttpResponse response;
93+
94+
private final Principal user;
95+
96+
private final Mono<WebSession> session;
97+
98+
99+
public MutativeDecorator(ServerWebExchange delegate,
100+
ServerHttpRequest request, ServerHttpResponse response, Principal user,
101+
Mono<WebSession> session) {
102+
103+
super(delegate);
104+
this.request = request;
105+
this.response = response;
106+
this.user = user;
107+
this.session = session;
108+
}
109+
110+
111+
@Override
112+
public ServerHttpRequest getRequest() {
113+
return (this.request != null ? this.request : getDelegate().getRequest());
114+
}
115+
116+
@Override
117+
public ServerHttpResponse getResponse() {
118+
return (this.response != null ? this.response : getDelegate().getResponse());
119+
}
120+
121+
@Override
122+
public Mono<WebSession> getSession() {
123+
return (this.session != null ? this.session : getDelegate().getSession());
124+
}
125+
126+
@SuppressWarnings("unchecked")
127+
@Override
128+
public <T extends Principal> Optional<T> getPrincipal() {
129+
return (this.user != null ? Optional.of((T) this.user) : getDelegate().getPrincipal());
130+
}
131+
}
132+
133+
}
134+

spring-web/src/main/java/org/springframework/web/server/ServerWebExchange.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,48 @@ public interface ServerWebExchange {
118118
*/
119119
boolean checkNotModified(String etag, Instant lastModified);
120120

121+
122+
/**
123+
* Return a builder to mutate properties of this exchange. The resulting
124+
* new exchange is an immutable {@link ServerWebExchangeDecorator decorator}
125+
* around the current exchange instance that returns mutated values, where
126+
* provided, or delegating to the decorated instance otherwise.
127+
*/
128+
default MutativeBuilder mutate() {
129+
return new DefaultServerWebExchangeMutativeBuilder(this);
130+
}
131+
132+
133+
/**
134+
* Builder for mutating properties of a {@link ServerWebExchange}.
135+
*/
136+
interface MutativeBuilder {
137+
138+
/**
139+
* Set the request to use.
140+
*/
141+
MutativeBuilder setRequest(ServerHttpRequest request);
142+
143+
/**
144+
* Set the response to use.
145+
*/
146+
MutativeBuilder setResponse(ServerHttpResponse response);
147+
148+
/**
149+
* Set the principal to use.
150+
*/
151+
MutativeBuilder setPrincipal(Principal user);
152+
153+
/**
154+
* Set the session to use.
155+
*/
156+
MutativeBuilder setSession(Mono<WebSession> session);
157+
158+
/**
159+
* Build an immutable wrapper that returning the mutated properties.
160+
*/
161+
ServerWebExchange build();
162+
163+
}
164+
121165
}

spring-web/src/main/java/org/springframework/web/server/ServerWebExchangeDecorator.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,26 @@
2727
import org.springframework.util.Assert;
2828

2929
/**
30-
* Wraps another {@link ServerWebExchange} and delegates all methods to it.
31-
* Sub-classes can override specific methods, e.g. {@link #getPrincipal()} to
32-
* return the authenticated user for the request.
30+
* A convenient base class for classes that need to wrap another
31+
* {@link ServerWebExchange}. Pre-implements all methods by delegating to the
32+
* wrapped instance.
33+
*
34+
* <p>Note that if the purpose for wrapping is simply to override specific
35+
* properties, e.g. {@link #getPrincipal()}, consider using
36+
* {@link ServerWebExchange#mutate()} instead.
3337
*
3438
* @author Rossen Stoyanchev
3539
* @since 5.0
40+
*
41+
* @see ServerWebExchange#mutate()
3642
*/
3743
public class ServerWebExchangeDecorator implements ServerWebExchange {
3844

3945
private final ServerWebExchange delegate;
4046

4147

42-
public ServerWebExchangeDecorator(ServerWebExchange delegate) {
43-
Assert.notNull(delegate, "'delegate' is required.");
48+
protected ServerWebExchangeDecorator(ServerWebExchange delegate) {
49+
Assert.notNull(delegate, "ServerWebExchange 'delegate' is required.");
4450
this.delegate = delegate;
4551
}
4652

0 commit comments

Comments
 (0)