Current behaviour
WebHttpHandlerBuilder.build()
creates instance of HttpWebHandlerAdapter
(https://github.com/spring-projects/spring-framework/blob/master/spring-web/src/main/java/org/springframework/web/server/adapter/WebHttpHandlerBuilder.java#L356).
However, HttpWebHandlerAdapter allows to override some of it's methods (e.g. createExchange
).
Proposed behaviour
Supply HttpWebHandlerAdapterFactory
to WebHttpHandlerBuilder.build
and create HttpWebHandlerAdapter
via this factory. Naive approach could be as simple as:
public HttpHandler build() {
WebHandler decorated = new FilteringWebHandler(this.webHandler, this.filters);
decorated = new ExceptionHandlingWebHandler(decorated, this.exceptionHandlers);
HttpWebHandlerAdapter adapted = httpHandlerCreator.apply(decorated);
...
return adapted;
}
Motivation
Sometimes we need to decorate ServerHttpResponse
and ServerHttpRequest
(e.g. body logging/caching). Doing this inside a WebFilter
is not sufficient in case of thrown exception flow. We have to do it "earlier" than ExceptionHandlingWebHandler
Comment From: rstoyanchev
It's true HttpWebHandlerAdapter
has a couple of protected methods although probably more an oversight than intent due to the lack of Javadoc or an option to customize via WebHttpHandlerBuilder
.
Rather than exposing all of HttpWebHandlerAdapter
in this way we could add a couple of methods that can decorate the request and/or the response which would be invoked before the exchange is created. Another option is an HttpHandler
decorator. That would effectively decorate the HttpWebHandlerAdapter
itself. I like this latter option.
Comment From: sp00m
We were facing the same issue on https://github.com/qudini/qudini-reactive/pull/40: we needed to populate the reactive context "around" the ExceptionHandlingWebHandler
(i.e. not via WebFilter
), so that uncaught exceptions still have a debugging context when logged (which is quite convoluted to do given the manual instantiation of HttpWebHandlerAdapter
).
Do you think we could have an additional webHandlerDecorator
, the same way we now have this new httpHandlerDecorator
? This would hook just after decorated = new ExceptionHandlingWebHandler(decorated, this.exceptionHandlers);
, and would allow us to deal with the enhanced ServerWebExchange
instead of the ServerHttpRequest
/ServerHttpResponse
pair.
Also, do you think the static builder WebHttpHandlerBuilder#applicationContext(ApplicationContext)
could initialise those decorators by looking for specific beans in the context somehow? I guess custom interfaces will be needed (possibly inheriting Function<HttpHandler, HttpHandler>
/Function<WebHandler, WebHandler>
for backward compatibility).
I'm happy to contribute if you agree with the above.