You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have a WebFlux application with many controllers, and the particular need of having to pre-process and inject additional data in some cases.
In order to do so, a WebFilter is used, and the ServerHttpRequest as well as its containing ServerWebExchange is mutated through their .mutate() methods.
Additionally, I use Spring Boot 2.3.1+, which comes with a new spring.webflux.base-path configuration property that seemingly sets up a ContextPathCompositeHandler to emulate how the context path is handled in, e.g., servlets.
Issue
The problem here is that setting a WebFilter that mutates the incoming ServerHttpRequest seems to break WebFlux applications that are using the new Spring Boot spring.webflux.base-path. Requests end up never being routed to their respective controllers, and the affected URLs will always return a 404 Not Found HTTP response.
While this is a Spring Boot configuration property, I believe that it is caused by an underlying Spring Web bug:
getRequest().getPath().pathWithinApplication() from ServerWebExchange seems to be used for routing by Spring WebFlux, as evidenced by this line in AbstractUrlHandlerMapping.
When the request is mutated again by the WebFilter, neither the uriPath nor the contextPath is copied into the internally used builder. The URI itself is copied, but the information about which part is the internal application path and which part is the context path is lost.
While I'm not 100% sure that this is a bug (this might be intended?), I think that it is fair to expect no information to be lost or changed when a ServerHttpRequest is mutated - except of course the parts that are explicitly written otherwise.
Resolution
I think that changing the mutate() method mentioned above to create a carbon copy of the initial ServerHttpRequest is the way to go - or at least using its getPath().contextPath() as the default context path in DefaultServerHttpRequestBuilder. It would definitely fix the problem, although I'm not entirely sure about backwards compatibility.
As such, and since I wasn't even sure whether it was a bug or not, I wanted to open a discussion first and didn't try to fix it myself - although I would gladly open a pull request if this is confirmed to be a bug and the proposed resolution seems acceptable.
Example
I quickly built a small, straightforward Spring Boot project that reproduces and demonstrates the issue.
This commit ensures that when mutating `ServerHttpRequest` instances,
the original contextPath information is copied to the request being
built.
Note that mutation on the `contextPath(String)` or `path(String)` should
be reflected to the other. (See their Javadoc for more information).
Fixesspring-projectsgh-25279
Affects: Spring Framework 5.2.7
Context
I have a WebFlux application with many controllers, and the particular need of having to pre-process and inject additional data in some cases.
In order to do so, a
WebFilter
is used, and theServerHttpRequest
as well as its containingServerWebExchange
is mutated through their.mutate()
methods.Additionally, I use Spring Boot 2.3.1+, which comes with a new
spring.webflux.base-path
configuration property that seemingly sets up aContextPathCompositeHandler
to emulate how the context path is handled in, e.g., servlets.Issue
The problem here is that setting a
WebFilter
that mutates the incomingServerHttpRequest
seems to break WebFlux applications that are using the new Spring Bootspring.webflux.base-path
. Requests end up never being routed to their respective controllers, and the affected URLs will always return a 404 Not Found HTTP response.While this is a Spring Boot configuration property, I believe that it is caused by an underlying Spring Web bug:
getRequest().getPath().pathWithinApplication()
fromServerWebExchange
seems to be used for routing by Spring WebFlux, as evidenced by this line inAbstractUrlHandlerMapping
.ContextPathCompositeHandler
by mutating the context path of the incoming request.WebFilter
, neither theuriPath
nor thecontextPath
is copied into the internally used builder. The URI itself is copied, but the information about which part is the internal application path and which part is the context path is lost.While I'm not 100% sure that this is a bug (this might be intended?), I think that it is fair to expect no information to be lost or changed when a
ServerHttpRequest
is mutated - except of course the parts that are explicitly written otherwise.Resolution
I think that changing the
mutate()
method mentioned above to create a carbon copy of the initialServerHttpRequest
is the way to go - or at least using itsgetPath().contextPath()
as the default context path inDefaultServerHttpRequestBuilder
. It would definitely fix the problem, although I'm not entirely sure about backwards compatibility.As such, and since I wasn't even sure whether it was a bug or not, I wanted to open a discussion first and didn't try to fix it myself - although I would gladly open a pull request if this is confirmed to be a bug and the proposed resolution seems acceptable.
Example
I quickly built a small, straightforward Spring Boot project that reproduces and demonstrates the issue.
demo.zip
Related issues
I only found one similar issue that might be related to this underlying "bug":
The text was updated successfully, but these errors were encountered: