Description
Describe the bug
With Spring Boot 3.3.4
and Spring Cloud 2024.0.1
along with spring-security-web dependency, inside implementation of custom WebFilter
, the exchange object provided of StrictFirewallServerWebExchange
type.
This class StrictFirewallServerWebExchange
is defined at org.springframework.security.web.server.firewall.StrictServerWebExchangeFirewall
and it has private implementation of decorators and builds for ServerWebExchange
and ServerHttpRequest
.
It is supposed to provide mutation on request object by using method like:
val buildRequest = request
.mutate()
.header("xyz", "abc")
.build()
Expected behavior is after mutation it should return instance of StrictFirewallHttpRequest
but it returns org.springframework.http.server.reactive.DefaultServerHttpRequestBuilder$MutatedServerHttpRequest
.
This creates issue whenever request is modified using WebFilter
, there is no impact of changes.
To Reproduce
- Create a sample reactive spring boot application with spring security, Http firewall
- Add a pre
WebFilter
- Try to mutate exchange like this:
var buildRequest = exchange.request .mutate() .header("xyz", "abc") .build() var buildExchange = exchange.mutate().request(buildRequest).build()
- Either check returned
buildExchange
type or do thechain.filter(buildExchange)
and see the endpoint result.
Expected behavior
If we do mutation like (without adding header), it results correct instance:
var buildRequest = exchange.request
.mutate()
.build()
Similarly, when we modify request and a header like:
var buildRequest = exchange.request .mutate() .header("xyz", "abc") .build() var buildExchange = exchange.mutate().request(buildRequest).build()
It should also return correct instance (of StrictFirewallHttpRequest
) but it returns:
While investigation, found that StrictFirewallBuilder.header(String headerName, String... headerValues)
method calls same method on delegated object which returns DefaultServerHttpRequestBuilder
type while ideally this method should wrap into StrictFirewallBuilder
type:
public ServerHttpRequest.Builder header(String headerName, String... headerValues) {
return this.delegate.header(headerName, headerValues);
}