M. Justin opened SPR-10707 and commented
I would like to be able to use RestTemplate with a nonstandard HTTP method that's not found in the list of 8 provided in the HttpMethod enum. Specifically, I would like to do a "PURGE" request against a Varnish cache. Such an enhancement would also allow calling other APIs with nonstandard HTTP methods, such as the various WebDAV methods.
Looking at the spring-web source code, it looks like there is currently no way of working around this while still using the library, since the HttpMethod is used exclusively throughout the code except where converted to a name to interface with the underlying HTTP library (e.g. SimpleClientHttpRequestFactory).
I would like to see a version of the exchange/execute API that takes in either an arbitrary status String, or have an interface that HttpStatus implements that could be provided in cases like this. For a concrete example of what I'm referring to (but applied to status codes rather than HTTP methods), see Status and StatusType in JAX-RS.
3 votes, 7 watchers
Comment From: spring-projects-issues
M. Justin commented
This can be solved within Java using the HTTP Client library: http://stackoverflow.com/a/12949573/1108305. That said, it still seems like it would be good to provide a way of doing this in RestTemplate, so that multiple different APIs/configurations for the same type of thing wouldn't be needed.
Comment From: spring-projects-issues
Phil Webb commented
I like the idea of an interface that HttpMethod could implement, however, that enum is used in quite a few places and it might be hard to make such a change without breaking backwards binary compatibility. Another issue is that the SimpleClientHttpRequestFactory only works with specific methods so to support a custom option you would need to use the the Apache HttpClient project.
Whilst not ideal, you might be able to write an new version of HttpComponentsClientHttpRequestFactory that changes one of the existing method (DELETE perhaps) to PURGE.
Comment From: spring-projects-issues
Jiri Mikulasek commented
is there a plan for this? Once implemented it would significantly increase the range of RestTemplate's use cases.
Comment From: spring-projects-issues
Bulk closing outdated, unresolved issues. Please, reopen if still relevant.
Comment From: mjustin
Still relevant.
Comment From: rstoyanchev
@mjustin could you elaborate if your use case is for the same example as in the original comment?
Comment From: rstoyanchev
Never mind, I just realized you are probably the original reporter ? :)
Comment From: bclozel
Hi @mjustin
The Framework team has discussed this issue in more details; here's our current understanding.
Adding support for non-standard HTTP methods, in general would mean:
- checking that all currently supported clients and servers are supporting that
- adding method variants with String and adding
@Nullablewhere needed - globally aligning the support (mapping annotations, and so on) if we want to support that properly in our programming model
While 2) and 3) are adding a complexity cost to the API and our codebase (and we can decide if it's worth it), 1) seems a bit harder since clients and servers don't seem to provide strong guarantees for that. For example, the JDK11 client will throw an IllegalArgumentException if the method name is not valid, see RFC 7230 section-3.1.1, or the method is restricted by the implementation.
On the other hand, it seems that those custom HTTP methods aren't widely supported nor mandatory to reach the same end goal. For example, the Varnish documentation mentions that you need to add specific code snippets to your configuration to support that. Moreover, looking at those configuration bits, using a specific HTTP header or any other signal in the HTTP request would work as well.
With that in mind, we're leaning on not supporting this, but we'd like to hear from you and get a better sense of how critical or widely supported is this. Also, what kind of added value RestTemplate provides for those cases instead of using an HTTP client library directly - are you expected to decode a returned response body using JSON?
Thanks!
Comment From: mjustin
Never mind, I just realized you are probably the original reporter ? :)
Correct, I was the original reporter. :-)
Comment From: mjustin
As alluded to in my follow-up comment on the issue, we were able to work around this by using the Apache HttpClient library. Really, the main issues with this approach were the need to pull in a second library for certain types of requests (with the need to use two separate APIs), and the need to make sure any configuration changes were applied to both libraries using their different APIs.
So it's definitely doable to do it cross-library. It's really just the matter of having to solve the same problem in different ways in the same application for operations which are both conceptually and fundamentally similar.
As for decoding the returned response body, I believe with the way things were configured we didn't really need it for our use case; the response status code of the request was enough.
As for needing to add specific code snippets to Varnish, that's true, but in order to allow purging at all you need to add some custom configuration to the Varnish configuration. Per the referenced Varnish documentation, the standard approach in Varnish is indeed to use the PURGE method.
Usually a purge is invoked through HTTP with the method PURGE.
So any alternative approaches would be deviating from the recommended Varnish standard just to support a particular Java library that's interfacing with it. Note also that Varnish isn't the only system to use the PURGE HTTP method; the Squid cache also supports it (http://etutorials.org/Server+Administration/Squid.+The+definitive+guide/Chapter+7.+Disk+Cache+Basics/7.6+Removing+Cached+Objects/).
Comment From: bclozel
This issue has been discussed for a while now and we've never reached a point where we could implement that in a consistent manner and where the new use cases covered would be important enough to justify the cost associated with this.
We've put RestTemplate in maintenance mode since - so we won't be adding new features nor changing its API in the future. We could consider this for WebClient, but we'd be stuck with the same problems because WebClient can be used on top of several connectors, some of them not supporting custom methods.
We advise developers to use workarounds on the server side (using other means of issuing such requests) or using a low-level HTTP client directly. I'm closing this issue as a result.
Comment From: mjustin
Thanks for the thorough explanation behind the decision and the tradeoffs considered in making it. While not the most convenient situation from a usability standpoint, it is certainly understandable.