Skip to content

Commit b72ff25

Browse files
committed
Relocate and unify reactive cookie properties
Relocate the recently introduced `spring.webflux.session` properties to `server.reactive.session` and create a unified `Cookie` properties class. Reactive session properties now mirror the existing `server.servlet.session` properties and better reflect the fact that they are related to the server and not just for WebFlux. See gh-26714
1 parent 3c71637 commit b72ff25

File tree

13 files changed

+422
-351
lines changed

13 files changed

+422
-351
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoReactiveSessionConfiguration.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2323
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2424
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
25-
import org.springframework.boot.autoconfigure.web.reactive.WebFluxProperties;
25+
import org.springframework.boot.autoconfigure.web.ServerProperties;
2626
import org.springframework.boot.context.properties.EnableConfigurationProperties;
2727
import org.springframework.context.annotation.Conditional;
2828
import org.springframework.context.annotation.Configuration;
@@ -50,8 +50,9 @@ static class SpringBootReactiveMongoWebSessionConfiguration extends ReactiveMong
5050

5151
@Autowired
5252
void customize(SessionProperties sessionProperties, MongoSessionProperties mongoSessionProperties,
53-
WebFluxProperties webFluxProperties) {
54-
Duration timeout = sessionProperties.determineTimeout(() -> webFluxProperties.getSession().getTimeout());
53+
ServerProperties serverProperties) {
54+
Duration timeout = sessionProperties
55+
.determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout());
5556
if (timeout != null) {
5657
setMaxInactiveIntervalInSeconds((int) timeout.getSeconds());
5758
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisReactiveSessionConfiguration.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2323
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2424
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
25-
import org.springframework.boot.autoconfigure.web.reactive.WebFluxProperties;
25+
import org.springframework.boot.autoconfigure.web.ServerProperties;
2626
import org.springframework.boot.context.properties.EnableConfigurationProperties;
2727
import org.springframework.context.annotation.Conditional;
2828
import org.springframework.context.annotation.Configuration;
@@ -50,8 +50,9 @@ static class SpringBootRedisWebSessionConfiguration extends RedisWebSessionConfi
5050

5151
@Autowired
5252
void customize(SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties,
53-
WebFluxProperties webFluxProperties) {
54-
Duration timeout = sessionProperties.determineTimeout(() -> webFluxProperties.getSession().getTimeout());
53+
ServerProperties serverProperties) {
54+
Duration timeout = sessionProperties
55+
.determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout());
5556
if (timeout != null) {
5657
setMaxInactiveIntervalInSeconds((int) timeout.getSeconds());
5758
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionAutoConfiguration.java

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration;
4646
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
4747
import org.springframework.boot.autoconfigure.web.reactive.WebFluxProperties;
48-
import org.springframework.boot.autoconfigure.web.reactive.WebFluxProperties.SameSite;
48+
import org.springframework.boot.autoconfigure.web.reactive.WebSessionIdResolverAutoConfiguration;
4949
import org.springframework.boot.context.properties.EnableConfigurationProperties;
5050
import org.springframework.boot.context.properties.PropertyMapper;
5151
import org.springframework.boot.web.servlet.server.Session.Cookie;
@@ -56,7 +56,6 @@
5656
import org.springframework.context.annotation.Import;
5757
import org.springframework.context.annotation.ImportSelector;
5858
import org.springframework.core.type.AnnotationMetadata;
59-
import org.springframework.http.ResponseCookie.ResponseCookieBuilder;
6059
import org.springframework.security.web.authentication.RememberMeServices;
6160
import org.springframework.session.ReactiveSessionRepository;
6261
import org.springframework.session.Session;
@@ -66,9 +65,6 @@
6665
import org.springframework.session.web.http.CookieSerializer;
6766
import org.springframework.session.web.http.DefaultCookieSerializer;
6867
import org.springframework.session.web.http.HttpSessionIdResolver;
69-
import org.springframework.util.StringUtils;
70-
import org.springframework.web.server.session.CookieWebSessionIdResolver;
71-
import org.springframework.web.server.session.WebSessionIdResolver;
7268

7369
/**
7470
* {@link EnableAutoConfiguration Auto-configuration} for Spring Session.
@@ -87,7 +83,8 @@
8783
@EnableConfigurationProperties({ ServerProperties.class, SessionProperties.class, WebFluxProperties.class })
8884
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, HazelcastAutoConfiguration.class,
8985
JdbcTemplateAutoConfiguration.class, MongoDataAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class,
90-
RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class })
86+
RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class,
87+
WebSessionIdResolverAutoConfiguration.class })
9188
@AutoConfigureBefore({ HttpHandlerAutoConfiguration.class, WebFluxAutoConfiguration.class })
9289
public class SessionAutoConfiguration {
9390

@@ -140,36 +137,6 @@ static class ServletSessionRepositoryConfiguration {
140137
@Import(ReactiveSessionRepositoryValidator.class)
141138
static class ReactiveSessionConfiguration {
142139

143-
private final WebFluxProperties webFluxProperties;
144-
145-
ReactiveSessionConfiguration(WebFluxProperties webFluxProperties) {
146-
this.webFluxProperties = webFluxProperties;
147-
}
148-
149-
@Bean
150-
@ConditionalOnMissingBean
151-
WebSessionIdResolver webSessionIdResolver() {
152-
WebFluxProperties.Cookie cookieProperties = this.webFluxProperties.getSession().getCookie();
153-
CookieWebSessionIdResolver webSessionIdResolver = new CookieWebSessionIdResolver();
154-
String cookieName = cookieProperties.getName();
155-
if (StringUtils.hasText(cookieName)) {
156-
webSessionIdResolver.setCookieName(cookieName);
157-
}
158-
webSessionIdResolver.addCookieInitializer(this::initializeCookie);
159-
return webSessionIdResolver;
160-
}
161-
162-
private void initializeCookie(ResponseCookieBuilder builder) {
163-
WebFluxProperties.Cookie cookie = this.webFluxProperties.getSession().getCookie();
164-
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
165-
map.from(cookie::getDomain).to(builder::domain);
166-
map.from(cookie::getPath).to(builder::path);
167-
map.from(cookie::getHttpOnly).to(builder::httpOnly);
168-
map.from(cookie::getSecure).to(builder::secure);
169-
map.from(cookie::getMaxAge).to(builder::maxAge);
170-
map.from(cookie::getSameSite).as(SameSite::attribute).to(builder::sameSite);
171-
}
172-
173140
@Configuration(proxyBeanMethods = false)
174141
@ConditionalOnMissingBean(ReactiveSessionRepository.class)
175142
@Import({ ReactiveSessionRepositoryImplementationValidator.class,

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.springframework.boot.context.properties.NestedConfigurationProperty;
3535
import org.springframework.boot.convert.DurationUnit;
3636
import org.springframework.boot.web.server.Compression;
37+
import org.springframework.boot.web.server.Cookie;
3738
import org.springframework.boot.web.server.Http2;
3839
import org.springframework.boot.web.server.Shutdown;
3940
import org.springframework.boot.web.server.Ssl;
@@ -116,6 +117,8 @@ public class ServerProperties {
116117

117118
private final Servlet servlet = new Servlet();
118119

120+
private final Reactive reactive = new Reactive();
121+
119122
private final Tomcat tomcat = new Tomcat();
120123

121124
private final Jetty jetty = new Jetty();
@@ -188,6 +191,10 @@ public Servlet getServlet() {
188191
return this.servlet;
189192
}
190193

194+
public Reactive getReactive() {
195+
return this.reactive;
196+
}
197+
191198
public Tomcat getTomcat() {
192199
return this.tomcat;
193200
}
@@ -213,7 +220,7 @@ public void setForwardHeadersStrategy(ForwardHeadersStrategy forwardHeadersStrat
213220
}
214221

215222
/**
216-
* Servlet properties.
223+
* Servlet server properties.
217224
*/
218225
public static class Servlet {
219226

@@ -296,6 +303,44 @@ public Session getSession() {
296303

297304
}
298305

306+
/**
307+
* Reactive server properties.
308+
*/
309+
public static class Reactive {
310+
311+
private final Session session = new Session();
312+
313+
public Session getSession() {
314+
return this.session;
315+
}
316+
317+
public static class Session {
318+
319+
/**
320+
* Session timeout. If a duration suffix is not specified, seconds will be
321+
* used.
322+
*/
323+
@DurationUnit(ChronoUnit.SECONDS)
324+
private Duration timeout = Duration.ofMinutes(30);
325+
326+
private final Cookie cookie = new Cookie();
327+
328+
public Duration getTimeout() {
329+
return this.timeout;
330+
}
331+
332+
public void setTimeout(Duration timeout) {
333+
this.timeout = timeout;
334+
}
335+
336+
public Cookie getCookie() {
337+
return this.cookie;
338+
}
339+
340+
}
341+
342+
}
343+
299344
/**
300345
* Tomcat properties.
301346
*/

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java

Lines changed: 29 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.springframework.boot.autoconfigure.web.reactive;
1818

1919
import java.time.Duration;
20-
import java.util.function.Supplier;
2120

2221
import org.apache.commons.logging.Log;
2322
import org.apache.commons.logging.LogFactory;
@@ -37,15 +36,13 @@
3736
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
3837
import org.springframework.boot.autoconfigure.validation.ValidatorAdapter;
3938
import org.springframework.boot.autoconfigure.web.ConditionalOnEnabledResourceChain;
39+
import org.springframework.boot.autoconfigure.web.ServerProperties;
4040
import org.springframework.boot.autoconfigure.web.WebProperties;
4141
import org.springframework.boot.autoconfigure.web.WebProperties.Resources;
4242
import org.springframework.boot.autoconfigure.web.format.DateTimeFormatters;
4343
import org.springframework.boot.autoconfigure.web.format.WebConversionService;
44-
import org.springframework.boot.autoconfigure.web.reactive.WebFluxProperties.Cookie;
4544
import org.springframework.boot.autoconfigure.web.reactive.WebFluxProperties.Format;
46-
import org.springframework.boot.autoconfigure.web.reactive.WebFluxProperties.SameSite;
4745
import org.springframework.boot.context.properties.EnableConfigurationProperties;
48-
import org.springframework.boot.context.properties.PropertyMapper;
4946
import org.springframework.boot.convert.ApplicationConversionService;
5047
import org.springframework.boot.web.codec.CodecCustomizer;
5148
import org.springframework.boot.web.reactive.filter.OrderedHiddenHttpMethodFilter;
@@ -57,10 +54,8 @@
5754
import org.springframework.core.annotation.Order;
5855
import org.springframework.format.FormatterRegistry;
5956
import org.springframework.format.support.FormattingConversionService;
60-
import org.springframework.http.ResponseCookie.ResponseCookieBuilder;
6157
import org.springframework.http.codec.ServerCodecConfigurer;
6258
import org.springframework.util.ClassUtils;
63-
import org.springframework.util.StringUtils;
6459
import org.springframework.validation.Validator;
6560
import org.springframework.web.filter.reactive.HiddenHttpMethodFilter;
6661
import org.springframework.web.reactive.config.DelegatingWebFluxConfiguration;
@@ -83,7 +78,6 @@
8378
import org.springframework.web.server.i18n.AcceptHeaderLocaleContextResolver;
8479
import org.springframework.web.server.i18n.FixedLocaleContextResolver;
8580
import org.springframework.web.server.i18n.LocaleContextResolver;
86-
import org.springframework.web.server.session.CookieWebSessionIdResolver;
8781
import org.springframework.web.server.session.DefaultWebSessionManager;
8882
import org.springframework.web.server.session.InMemoryWebSessionStore;
8983
import org.springframework.web.server.session.WebSessionIdResolver;
@@ -108,7 +102,8 @@
108102
@ConditionalOnClass(WebFluxConfigurer.class)
109103
@ConditionalOnMissingBean({ WebFluxConfigurationSupport.class })
110104
@AutoConfigureAfter({ ReactiveWebServerFactoryAutoConfiguration.class, CodecsAutoConfiguration.class,
111-
ReactiveMultipartAutoConfiguration.class, ValidationAutoConfiguration.class })
105+
ReactiveMultipartAutoConfiguration.class, ValidationAutoConfiguration.class,
106+
WebSessionIdResolverAutoConfiguration.class })
112107
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
113108
public class WebFluxAutoConfiguration {
114109

@@ -240,19 +235,22 @@ private void customizeResourceHandlerRegistration(ResourceHandlerRegistration re
240235
* Configuration equivalent to {@code @EnableWebFlux}.
241236
*/
242237
@Configuration(proxyBeanMethods = false)
243-
@EnableConfigurationProperties(WebProperties.class)
238+
@EnableConfigurationProperties({ WebProperties.class, ServerProperties.class })
244239
public static class EnableWebFluxConfiguration extends DelegatingWebFluxConfiguration {
245240

246241
private final WebFluxProperties webFluxProperties;
247242

248243
private final WebProperties webProperties;
249244

245+
private final ServerProperties serverProperties;
246+
250247
private final WebFluxRegistrations webFluxRegistrations;
251248

252249
public EnableWebFluxConfiguration(WebFluxProperties webFluxProperties, WebProperties webProperties,
253-
ObjectProvider<WebFluxRegistrations> webFluxRegistrations) {
250+
ServerProperties serverProperties, ObjectProvider<WebFluxRegistrations> webFluxRegistrations) {
254251
this.webFluxProperties = webFluxProperties;
255252
this.webProperties = webProperties;
253+
this.serverProperties = serverProperties;
256254
this.webFluxRegistrations = webFluxRegistrations.getIfUnique();
257255
}
258256

@@ -313,54 +311,12 @@ public LocaleContextResolver localeContextResolver() {
313311
@ConditionalOnMissingBean(name = WebHttpHandlerBuilder.WEB_SESSION_MANAGER_BEAN_NAME)
314312
public WebSessionManager webSessionManager(ObjectProvider<WebSessionIdResolver> webSessionIdResolver) {
315313
DefaultWebSessionManager webSessionManager = new DefaultWebSessionManager();
316-
Duration timeout = this.webFluxProperties.getSession().getTimeout();
314+
Duration timeout = this.serverProperties.getReactive().getSession().getTimeout();
317315
webSessionManager.setSessionStore(new MaxIdleTimeInMemoryWebSessionStore(timeout));
318-
webSessionManager.setSessionIdResolver(webSessionIdResolver.getIfAvailable(cookieWebSessionIdResolver()));
316+
webSessionIdResolver.ifAvailable(webSessionManager::setSessionIdResolver);
319317
return webSessionManager;
320318
}
321319

322-
private Supplier<WebSessionIdResolver> cookieWebSessionIdResolver() {
323-
return () -> {
324-
CookieWebSessionIdResolver resolver = new CookieWebSessionIdResolver();
325-
String cookieName = this.webFluxProperties.getSession().getCookie().getName();
326-
if (StringUtils.hasText(cookieName)) {
327-
resolver.setCookieName(cookieName);
328-
}
329-
resolver.addCookieInitializer(this::initializeCookie);
330-
return resolver;
331-
};
332-
}
333-
334-
private void initializeCookie(ResponseCookieBuilder builder) {
335-
Cookie cookie = this.webFluxProperties.getSession().getCookie();
336-
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
337-
map.from(cookie::getDomain).to(builder::domain);
338-
map.from(cookie::getPath).to(builder::path);
339-
map.from(cookie::getHttpOnly).to(builder::httpOnly);
340-
map.from(cookie::getSecure).to(builder::secure);
341-
map.from(cookie::getMaxAge).to(builder::maxAge);
342-
map.from(cookie::getSameSite).as(SameSite::attribute).to(builder::sameSite);
343-
}
344-
345-
static final class MaxIdleTimeInMemoryWebSessionStore extends InMemoryWebSessionStore {
346-
347-
private final Duration timeout;
348-
349-
private MaxIdleTimeInMemoryWebSessionStore(Duration timeout) {
350-
this.timeout = timeout;
351-
}
352-
353-
@Override
354-
public Mono<WebSession> createWebSession() {
355-
return super.createWebSession().doOnSuccess(this::setMaxIdleTime);
356-
}
357-
358-
private void setMaxIdleTime(WebSession session) {
359-
session.setMaxIdleTime(this.timeout);
360-
}
361-
362-
}
363-
364320
}
365321

366322
@Configuration(proxyBeanMethods = false)
@@ -375,4 +331,23 @@ ResourceChainResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCu
375331

376332
}
377333

334+
static final class MaxIdleTimeInMemoryWebSessionStore extends InMemoryWebSessionStore {
335+
336+
private final Duration timeout;
337+
338+
private MaxIdleTimeInMemoryWebSessionStore(Duration timeout) {
339+
this.timeout = timeout;
340+
}
341+
342+
@Override
343+
public Mono<WebSession> createWebSession() {
344+
return super.createWebSession().doOnSuccess(this::setMaxIdleTime);
345+
}
346+
347+
private void setMaxIdleTime(WebSession session) {
348+
session.setMaxIdleTime(this.timeout);
349+
}
350+
351+
}
352+
378353
}

0 commit comments

Comments
 (0)