From caaf48d4ec8dc660387f7ed05db6956c20a547a8 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Wed, 12 Jan 2022 07:00:45 +0000 Subject: [PATCH 1/5] Add missing overrides to ServerHttpResponseDecorator Closes gh-27889 --- .../server/reactive/ServerHttpResponseDecorator.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/ServerHttpResponseDecorator.java b/spring-web/src/main/java/org/springframework/http/server/reactive/ServerHttpResponseDecorator.java index 79a6c0c8bd..c6574c26f3 100644 --- a/spring-web/src/main/java/org/springframework/http/server/reactive/ServerHttpResponseDecorator.java +++ b/spring-web/src/main/java/org/springframework/http/server/reactive/ServerHttpResponseDecorator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -65,6 +65,16 @@ public class ServerHttpResponseDecorator implements ServerHttpResponse { return getDelegate().getStatusCode(); } + @Override + public boolean setRawStatusCode(@Nullable Integer value) { + return getDelegate().setRawStatusCode(value); + } + + @Override + public Integer getRawStatusCode() { + return getDelegate().getRawStatusCode(); + } + @Override public HttpHeaders getHeaders() { return getDelegate().getHeaders(); From f63a106c85f3135d82c5ceca375e8f9e6c8a5535 Mon Sep 17 00:00:00 2001 From: Max Demydenko Date: Wed, 5 Jan 2022 01:41:37 +0200 Subject: [PATCH 2/5] clear() method also clears argument resolver cache See gh-27888 --- .../invocation/HandlerMethodArgumentResolverComposite.java | 1 + .../reactive/HandlerMethodArgumentResolverComposite.java | 1 + .../method/support/HandlerMethodArgumentResolverComposite.java | 1 + .../result/method/HandlerMethodArgumentResolverComposite.java | 1 + 4 files changed, 4 insertions(+) diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/HandlerMethodArgumentResolverComposite.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/HandlerMethodArgumentResolverComposite.java index 7bde7fb3d3..22584b700a 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/HandlerMethodArgumentResolverComposite.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/HandlerMethodArgumentResolverComposite.java @@ -88,6 +88,7 @@ public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgu */ public void clear() { this.argumentResolvers.clear(); + this.argumentResolverCache.clear(); } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/HandlerMethodArgumentResolverComposite.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/HandlerMethodArgumentResolverComposite.java index 3009a05e56..5fd91af841 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/HandlerMethodArgumentResolverComposite.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/HandlerMethodArgumentResolverComposite.java @@ -90,6 +90,7 @@ public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgu */ public void clear() { this.argumentResolvers.clear(); + this.argumentResolverCache.clear(); } diff --git a/spring-web/src/main/java/org/springframework/web/method/support/HandlerMethodArgumentResolverComposite.java b/spring-web/src/main/java/org/springframework/web/method/support/HandlerMethodArgumentResolverComposite.java index 60a27b9ae5..cc13867d20 100644 --- a/spring-web/src/main/java/org/springframework/web/method/support/HandlerMethodArgumentResolverComposite.java +++ b/spring-web/src/main/java/org/springframework/web/method/support/HandlerMethodArgumentResolverComposite.java @@ -90,6 +90,7 @@ public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgu */ public void clear() { this.argumentResolvers.clear(); + this.argumentResolverCache.clear(); } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/HandlerMethodArgumentResolverComposite.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/HandlerMethodArgumentResolverComposite.java index 46baa13c5f..b2013e22e2 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/HandlerMethodArgumentResolverComposite.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/HandlerMethodArgumentResolverComposite.java @@ -87,6 +87,7 @@ class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentRes */ public void clear() { this.argumentResolvers.clear(); + this.argumentResolverCache.clear(); } From 7665424ea83034456af87324edc5db9b29a1a948 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Wed, 12 Jan 2022 07:08:01 +0000 Subject: [PATCH 3/5] Polishing contribution Closes gh-27888 --- .../invocation/HandlerMethodArgumentResolverComposite.java | 4 ++-- .../reactive/HandlerMethodArgumentResolverComposite.java | 4 ++-- .../support/HandlerMethodArgumentResolverComposite.java | 4 ++-- .../result/method/HandlerMethodArgumentResolverComposite.java | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/HandlerMethodArgumentResolverComposite.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/HandlerMethodArgumentResolverComposite.java index 22584b700a..966fa70834 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/HandlerMethodArgumentResolverComposite.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/HandlerMethodArgumentResolverComposite.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -84,7 +84,7 @@ public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgu } /** - * Clear the list of configured resolvers. + * Clear the list of configured resolvers and the resolver cache. */ public void clear() { this.argumentResolvers.clear(); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/HandlerMethodArgumentResolverComposite.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/HandlerMethodArgumentResolverComposite.java index 5fd91af841..fc73bf63de 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/HandlerMethodArgumentResolverComposite.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/HandlerMethodArgumentResolverComposite.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -86,7 +86,7 @@ public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgu } /** - * Clear the list of configured resolvers. + * Clear the list of configured resolvers and the resolver cache. */ public void clear() { this.argumentResolvers.clear(); diff --git a/spring-web/src/main/java/org/springframework/web/method/support/HandlerMethodArgumentResolverComposite.java b/spring-web/src/main/java/org/springframework/web/method/support/HandlerMethodArgumentResolverComposite.java index cc13867d20..e9b5f6056c 100644 --- a/spring-web/src/main/java/org/springframework/web/method/support/HandlerMethodArgumentResolverComposite.java +++ b/spring-web/src/main/java/org/springframework/web/method/support/HandlerMethodArgumentResolverComposite.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -85,7 +85,7 @@ public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgu } /** - * Clear the list of configured resolvers. + * Clear the list of configured resolvers and the resolver cache. * @since 4.3 */ public void clear() { diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/HandlerMethodArgumentResolverComposite.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/HandlerMethodArgumentResolverComposite.java index b2013e22e2..351badb98e 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/HandlerMethodArgumentResolverComposite.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/HandlerMethodArgumentResolverComposite.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -83,7 +83,7 @@ class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentRes } /** - * Clear the list of configured resolvers. + * Clear the list of configured resolvers and the resolver cache. */ public void clear() { this.argumentResolvers.clear(); From 01231fe923659cfef2cb1e91b8b15ae6caf0da01 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Wed, 12 Jan 2022 07:20:58 +0000 Subject: [PATCH 4/5] Minor refactoring in STOMP documentation Closes gh-27906 --- src/docs/asciidoc/web/websocket.adoc | 30 ++++++++++++++++------------ 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/docs/asciidoc/web/websocket.adoc b/src/docs/asciidoc/web/websocket.adoc index 74f4a07658..c943dbe827 100644 --- a/src/docs/asciidoc/web/websocket.adoc +++ b/src/docs/asciidoc/web/websocket.adoc @@ -1724,19 +1724,11 @@ HTTP session (which is then associated with WebSocket or SockJS sessions created for that user) and results in a user header being stamped on every `Message` flowing through the application. -Note that the STOMP protocol does have `login` and `passcode` headers -on the `CONNECT` frame. Those were originally designed for and are still needed, -for example, for STOMP over TCP. However, for STOMP over WebSocket, by default, -Spring ignores authorization headers at the STOMP protocol level, assumes that -the user is already authenticated at the HTTP transport level, and expects that -the WebSocket or SockJS session contain the authenticated user. - -NOTE: Spring Security provides -https://docs.spring.io/spring-security/reference/servlet/integrations/websocket.html#websocket-authorization[WebSocket sub-protocol authorization] -that uses a `ChannelInterceptor` to authorize messages based on the user header in them. -Also, Spring Session provides -https://docs.spring.io/spring-session/reference/web-socket.html[WebSocket integration] -that ensures the user's HTTP session does not expire while the WebSocket session is still active. +The STOMP protocol does have `login` and `passcode` headers on the `CONNECT` frame. +Those were originally designed for and are needed for STOMP over TCP. However, for STOMP +over WebSocket, by default, Spring ignores authentication headers at the STOMP protocol +level, and assumes that the user is already authenticated at the HTTP transport level. +The expectation is that the WebSocket or SockJS session contain the authenticated user. @@ -1814,6 +1806,18 @@ its own implementation of `WebSocketMessageBrokerConfigurer` that is marked with +[[websocket-stomp-authorization]] +=== Authorization + +Spring Security provides +https://docs.spring.io/spring-security/reference/servlet/integrations/websocket.html#websocket-authorization[WebSocket sub-protocol authorization] +that uses a `ChannelInterceptor` to authorize messages based on the user header in them. +Also, Spring Session provides +https://docs.spring.io/spring-session/reference/web-socket.html[WebSocket integration] +that ensures the user's HTTP session does not expire while the WebSocket session is still active. + + + [[websocket-stomp-user-destination]] === User Destinations From 34cb5df8599f72401fc30e8d0b05ca0ac10a0840 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Wed, 12 Jan 2022 08:55:22 +0000 Subject: [PATCH 5/5] Consistent id for ReactorServerHttpRequest Closes gh-27885 --- .../reactive/AbstractServerHttpRequest.java | 13 ++++++++++-- .../reactive/ReactorServerHttpRequest.java | 20 +++++++++++++++---- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/AbstractServerHttpRequest.java b/spring-web/src/main/java/org/springframework/http/server/reactive/AbstractServerHttpRequest.java index 3b8bb8ad70..6c0ac9374e 100644 --- a/spring-web/src/main/java/org/springframework/http/server/reactive/AbstractServerHttpRequest.java +++ b/spring-web/src/main/java/org/springframework/http/server/reactive/AbstractServerHttpRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -218,9 +218,18 @@ public abstract class AbstractServerHttpRequest implements ServerHttpRequest { */ String getLogPrefix() { if (this.logPrefix == null) { - this.logPrefix = "[" + getId() + "] "; + this.logPrefix = "[" + initLogPrefix() + "] "; } return this.logPrefix; } + /** + * Subclasses can override this to provide the prefix to use for log messages. + *

By default, this is {@link #getId()}. + * @since 5.3.15 + */ + protected String initLogPrefix() { + return getId(); + } + } diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/ReactorServerHttpRequest.java b/spring-web/src/main/java/org/springframework/http/server/reactive/ReactorServerHttpRequest.java index 35db4de36c..72cdc1f9fc 100644 --- a/spring-web/src/main/java/org/springframework/http/server/reactive/ReactorServerHttpRequest.java +++ b/spring-web/src/main/java/org/springframework/http/server/reactive/ReactorServerHttpRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -77,7 +77,7 @@ class ReactorServerHttpRequest extends AbstractServerHttpRequest { private static URI initUri(HttpServerRequest request) throws URISyntaxException { Assert.notNull(request, "HttpServerRequest must not be null"); - return new URI(resolveBaseUrl(request).toString() + resolveRequestUri(request)); + return new URI(resolveBaseUrl(request) + resolveRequestUri(request)); } private static URI resolveBaseUrl(HttpServerRequest request) throws URISyntaxException { @@ -197,14 +197,26 @@ class ReactorServerHttpRequest extends AbstractServerHttpRequest { @Override @Nullable protected String initId() { + if (this.request instanceof Connection) { + return ((Connection) this.request).channel().id().asShortText() + + "-" + logPrefixIndex.incrementAndGet(); + } + return null; + } + + @Override + protected String initLogPrefix() { if (reactorNettyRequestChannelOperationsIdPresent) { - return (ChannelOperationsIdHelper.getId(this.request)); + String id = (ChannelOperationsIdHelper.getId(this.request)); + if (id != null) { + return id; + } } if (this.request instanceof Connection) { return ((Connection) this.request).channel().id().asShortText() + "-" + logPrefixIndex.incrementAndGet(); } - return null; + return getId(); }