groovy-wslite icon indicating copy to clipboard operation
groovy-wslite copied to clipboard

Getting java.net.ProtocolException: HTTP method DELETE doesn't support output

Open LuisMuniz opened this issue 9 years ago • 4 comments

Library version 1.1.2

When using the DELETE method on a URL, I found that the HttpClient failed with the above exception.

Caused by: java.net.ProtocolException: HTTP method DELETE doesn't support output
        at wslite.http.HTTPClient.setupConnection(HTTPClient.groovy:118)
        at wslite.http.HTTPClient.execute(HTTPClient.groovy:54)

In fact, the underlying HttpURLConnection is a sun.net.www.protocol.http.HttpURLConnection (using oracle jdk 7), and this implementation throws this exception when getOutputStream() is called and the method is not GET, POST, or PUT:

                if(this.method.equals("GET")) {
                    this.method = "POST";
                }

                if(!"POST".equals(this.method) && !"PUT".equals(this.method) && "http".equals(this.url.getProtocol())) {
                    throw new ProtocolException("HTTP method " + this.method + " doesn\'t support output");

It seems like the easy fix would be to change HttpClient.setupConnection to avoid trying to obtain the OutputStream of the response when executing a DELETE request.

LuisMuniz avatar Sep 24 '15 23:09 LuisMuniz

Actually looking at it more closely, this seems to be due to the fact that elasticsearch has a delete by query endpoint, which requires to send a DELETE request with a data payload.

The HttpUrlConnection implementation is overzealous in refusing this kind of request.

So here we are, looking at the code it does not seem obvious to use a different implementation of HttpURLConnection. What is weird is that when I use https, the error does not happen. So I'm kind of stuck. It seems like i will have to switch to another library. Any ideas?

LuisMuniz avatar Oct 27 '15 13:10 LuisMuniz

Yes, found out why when using https there is no exception:

if(!"POST".equals(this.method) && !"PUT".equals(this.method) && "http".equals(this.url.getProtocol()))

The last condition makes sure that this exception is only thrown in case of http. HttpsURLConnection delegates to this class for the underlying http protocol, but escapes this case, because the protocol is https obviously.

LuisMuniz avatar Oct 27 '15 14:10 LuisMuniz

@LuisMuniz, is this still an issue? I can create a pull request that only obtains the conn.outputstream in case the request method was POST/PUT/GET...

boekhold avatar Oct 19 '16 12:10 boekhold

Hi.

I have decided not to use this endpoint accepting DELETE with a body. This endpoint was being deprecated anyway, indicating the possibility that this was a bad idea.

LuisMuniz avatar Oct 19 '16 12:10 LuisMuniz