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.