HttpDelete with body
Asked Answered
G

5

42

I'm attempting to use an HttpDelete object to invoke a web service's delete method. The web service's code parses JSON from the message's body. However, I'm failing to understand how to add a body to an HttpDelete object. Is there a way to do this?

With HttpPut and HttpPost, I call the setEntity method and pass in my JSON. There doesn't appear to be any such method for HttpDelete.

If there is no way to set a body for an HttpDelete object, could you please link me to a resource that uses a super class of HttpDelete such that I can set the method (delete) and set a body. I know that isn't ideal, but at this point I can't alter the web service.

Gree answered 22/9, 2010 at 20:25 Comment(0)
B
99

Have you tried overriding HttpEntityEnclosingRequestBase as follows:

import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import java.net.URI;
import org.apache.http.annotation.NotThreadSafe;

@NotThreadSafe
class HttpDeleteWithBody extends HttpEntityEnclosingRequestBase {
    public static final String METHOD_NAME = "DELETE";
    public String getMethod() { return METHOD_NAME; }

    public HttpDeleteWithBody(final String uri) {
        super();
        setURI(URI.create(uri));
    }
    public HttpDeleteWithBody(final URI uri) {
        super();
        setURI(uri);
    }
    public HttpDeleteWithBody() { super(); }
}

That will create a HttpDelete-lookalike that has a setEntity method. I think the abstract class does almost everything for you, so that may be all that's needed.

FWIW, the code is based on this source to HttpPost that Google turned up.

Benoni answered 29/9, 2010 at 10:3 Comment(3)
Ugh! This doesn't appear to work with HttpURLConnection. I'm getting "java.net.ProtocolException: DELETE does not support writing". #10339115Yard
I'm with Scott... how do I do this with HttpURLConnection? I have to rewrite my network code to use Apache HTTP?Marivelmariya
It is not possible to have a DELETE with body with HttpURLConnection. I needed that and I ended up using HttpClient.Myxoma
M
9

Following Walter Mudnt advice, you can use this code. It works, just made it while testing my REST webservice.

try {
        HttpEntity entity = new StringEntity(jsonArray.toString());
        HttpClient httpClient = new DefaultHttpClient();
        HttpDeleteWithBody httpDeleteWithBody = new HttpDeleteWithBody("http://10.17.1.72:8080/contacts");
        httpDeleteWithBody.setEntity(entity);

        HttpResponse response = httpClient.execute(httpDeleteWithBody);

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

To access the response you can simply do: response.getStatusLine();

Mailemailed answered 10/4, 2014 at 10:3 Comment(0)
P
4

There are different interpretation in the question whether the body is allowed or not in the HTTP DELETE request. See this for example. In the HTTP 1.1 specification it is not explicitly prohibied. In my opinion you should not use body in the HTTP DELETE.

Nevertherless I think that you should use URL like mysite/myobject/objectId (shop.com/order/1234) where the objectId (a part of the url) is the additional information. As an alternative you can use URL parameters: mysite/myobject?objectName=table&color=red to send additipnal information to the server in the HTTP DELETE request. The part starting with '?' is the urlencoded parameters devided dy '&'.

If you want to send more complex information you can convert the data to JSON with respect of DataContractJsonSerializer or JavaScriptSerializer and then send the converted data (a string which I name myJsonData later) also as the parameter: mysite/myobject?objectInfo=myJsonData.

If you need to send too much additionnal data as a part of HTTP DELETE request so that you have problem with the URL length then you should probably better change the design of your application.

UPDATED: Iy you do want send some body per HTTP DELETE you can do this for example like following

// somewhere above add: using System.Net; and using System.IO;

WebClient myWebClient = new WebClient ();

// 1) version: do simple request    
string t= myWebClient.UploadString ("http://www.examples.com/", "DELETE", "bla bla");
// will be send following:
//
// DELETE http://www.examples.com/ HTTP/1.1
// Host: www.examples.com
// Content-Length: 7
// Expect: 100-continue
// Connection: Keep-Alive
//
//bla bla

// 2) version do complex request    
Stream stream = myWebClient.OpenWrite ("http://www.examples.com/", "DELETE");

string postData = "bla bla";
byte[] myDataAsBytes = Encoding.UTF8.GetBytes (postData);
stream.Write (myDataAsBytes, 0, myDataAsBytes.Length);
stream.Close (); // it send the data
// will be send following:
// 
// DELETE http://www.examples.com/ HTTP/1.1
// Host: www.examples.com
// Content-Length: 7
// Expect: 100-continue
// 
// bla bla

// 3) version
// create web request 
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create ("http://www.examples.com/");
webRequest.Method = "DELETE";
webRequest.ServicePoint.Expect100Continue = false;

// post data 
Stream requestStream = webRequest.GetRequestStream ();
StreamWriter requestWriter = new StreamWriter (requestStream);
requestWriter.Write (postData);
requestWriter.Close ();

//wait for server response 
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse ();
// send following:
// DELETE http://www.examples.com/ HTTP/1.1
// Host: www.examples.com
// Content-Length: 7
// Connection: Keep-Alive
// 
// bla bla

the full code could be a little more complex, but this one already will work. Nevertheless I continue to say that Web Service needed data in the body of HTTP DELETE request is bad designed.

Polynesia answered 29/9, 2010 at 9:52 Comment(7)
-1. The questioner said quite clearly that he cannot change the web service, and he probably didn't design it either. Since every recommendation in this post involves changing code not under control of the asker, it's completely unhelpful in the situation at hand.Benoni
For what it's worth, I don't disagree with your points on principle; a web service requiring DELETE methods with a body is probably poorly designed. Nonetheless, it is legitimate to ask how to interface with a badly-designed and possibly standards-noncompliant web service, and that is how I interpret this question.Benoni
@Walter Mundt: If one do need to send body in the HTTP DELETE I added an example with one of the possible way to do this.Polynesia
Could I ask why having a body with a delete method isn't a good idea? Is it just because people don't generally do it? It's certainly possible to do; so what's the reasoning for it being a bad idea? (I'm not disagreeing. I'm just inquiring. I'm new to web services)Gree
@Andrew: The most implementation of HTTP libraries classes and so on think that DELETE should has no body. In the case one have to have a VERY GOOD reason to design an implementation of a wen service which has this. Mostly one use not HTTP DELETE in RESTful services. In REST the url should identify resource, so HTTP DELETE has all information about the object which should be deleted in the URL. It is not prohibited to use HTTP GET with parameters to change resources or use HTTP PUT to delete resources, but it would be a bad style (bad design).Polynesia
@Polynesia can you share library details for above solution. maven dependency details ?Mischance
@PruthviChitrala: Sorry, but I used C# and .NET in my code example and no Java. Thus my code has no maven dependency - all are base classes existing in .Net: WebClient, Stream, StreamWriter and HttpWebRequest from System.Net and System.IO (see the first line of my code).Polynesia
J
3

use this,

class MyDelete extends HttpPost{
    public MyDelete(String url){
        super(url);
    }
    @Override
    public String getMethod() {
        return "DELETE";
    }
}
Joust answered 6/6, 2013 at 10:19 Comment(0)
S
0

in retrofit

import okhttp3.Request;

private final class ApiInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request oldRequest = chain.request();
        Request.Builder builder = oldRequest.newBuilder();
        if(condition) {
            return chain.proceed(builder.build().newBuilder().delete(builder.build().body()).build());
        }
        return chain.proceed(builder.build());
    }
}

you have to trigger condition, via something and potentially have to do some filtering for the url/header/body to remove the trigger,

unless the delete url/body/header is unique enough to not collide with post or get requests.

Stlouis answered 6/1, 2017 at 15:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.