Currently, Spring Boot seems to ingore the Content-Encoding header when dispatching a HTTP request received from a client. This manifests in unmarshalling error deep inside the Spring stack unless one adds an interceptor to transform any HttpServletRequest. Adding such an interceptor is cumbersome as the servlet API requires the implementation of a rather heavy wrapper object.
I argue that Spring Boot should be capable of detecting the header before disaptching to a controller. Ideally, Spring Boot should make an attempt to wrap the input stream before it is unmarshalled to apply unzipping. At a minimum, Spring Boot should detect that the header is present and present a better error message.
The decompression attempt could also be controlled by the server.compression.enabled property.
Comment From: wilkinsona
Adding such an interceptor is cumbersome as the servlet API requires the implementation of a rather heavy wrapper object.
IMO, server-side decompression of a request is best handled by the underlying container for this reason (among others). Unfortunately, I don't think support for request decompression is available across Jetty, Undertow, and Tomcat:
- There's an open request for enhancement in Jetty
- Tomcat doesn't support it, AFAIK
- Undertow added support in 1.4.7.Final
The Undertow issue makes this point:
This is actually not really part of the HTTP specification (as in theory a client has no way of knowing if a given server can understand the content encoded body).
That may go some way to explain the lack of container-level support for this.
Until container-level support for this becomes ubiquitous, I think it's unlikely that it's something that Spring Boot will support out of the box. Instead, I would recommend using Undertow as your embedded container and customising it to use an appropriately configured io.undertow.server.handlers.encoding.RequestEncodingHandler.
Comment From: raphw
You are right about that is not part of RFC 2616 but as it is also stated in the Undertow ticket, it is a fairly common function. Especially with REST-ish applications where PUT operations upload larger files, compression is often a rather important factor and I really would love if Spring Boot offered an easy opt-in to make this happen for controllers. As said, one can implement this without too much hassle using an interceptor but at where I am at, this requires me to copy-paste servlet code into multiple services.
I understand if you choose to not support such a non-standard feature but I would find it useful and I am sure I am not the only one, given that it was requested for at least two of the three HTTP servers supported by Spring Boot.
On a side note, I disagree with the statement that not knowing what format the server supports is breaking HTTP procedure. This is what Content-Negotiation is for; if a client sends an unsupported content-type, the client cannot know about such incompatibility before making the request either. This is what the 415 status code is for.
Comment From: bclozel
I agree with @wilkinsona - even if this feature might be useful, this is web server territory; we try to rely on containers for that because they're in a much better position when it comes to managing memory and flushing buffers.
@raphw you're right about HTTP 415 (the RFCs are now mentioning that explicitly). I guess the Undertow team meant that you have no way of knowing beforehand - you can just try and fail (but again, this is already the case if the client sends a Content-Type that the server does not support).
If you'd like this to move forward, I'd suggest to open a new issue on Tomcat's tracker. Suprisingly, I haven't found an existing one (my Bugzilla search skills aren't very good).
Comment From: raphw
You are probably right about the layer on which this problem should be solved. If Jetty has merged the already completed change set and if Tomcat decides to add this feature (https://bz.apache.org/bugzilla/show_bug.cgi?id=62072), maybe Spring Boot could offer a generic configuration property similar to the response encoding.
Comment From: wilkinsona
I'm watching both the Jetty and Tomcat issues but neither seems to have any traction at the moment. I'm going to close this issue for now. We can re-open it if the functionality becomes available in the future and look at what we need to do to make it readily available in Boot.
Comment From: wilkinsona
While the Jetty enhancement request is still open, the same or very similar functionality appears to have been included in 9.4. See https://github.com/eclipse/jetty.project/pull/964 for details. I'm still watching the Tomcat issue so we can re-open this if it's addressed. In the meantime, the functionality can be enabled relatively easily on Jetty and Undertow using a customiser.
Comment From: PRASANTHRAJENDRAN
Has anyone done any efficient workaround to handle the compressed request on the client-side, something like a customized interceptor/ Filter to transform such HttpServletRequest? If any could you share the intercepter/ Filter in Github? Because I am using the tomcat embedded server and still request ticket has not taken into consideration.
Comment From: amrith92
We found this as a useful workaround for configuring it for a embedded netty server: https://stackoverflow.com/a/59300909/1919302
I think it would be great to have at least an optional plugin / autoconfiguration to avoid having to add this functionality in every project.