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.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Andrew
  • 20,756
  • 32
  • 99
  • 177

5 Answers5

98

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.

Walter Mundt
  • 24,753
  • 5
  • 53
  • 61
  • Ugh! This doesn't appear to work with HttpURLConnection. I'm getting "java.net.ProtocolException: DELETE does not support writing". http://stackoverflow.com/questions/10338615/sending-http-delete-request-in-android – Scott Roberts Sep 30 '13 at 14:45
  • I'm with Scott... how do I do this with HttpURLConnection? I have to rewrite my network code to use Apache HTTP? – Greg Ennis Mar 03 '14 at 16:37
  • It is not possible to have a DELETE with body with HttpURLConnection. I needed that and I ended up using HttpClient. – NikosDim May 14 '14 at 11:16
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();

dazito
  • 7,740
  • 15
  • 75
  • 117
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.

Community
  • 1
  • 1
Oleg
  • 220,925
  • 34
  • 403
  • 798
  • 1
    -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. – Walter Mundt Sep 29 '10 at 09:57
  • 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. – Walter Mundt Sep 29 '10 at 10:16
  • @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. – Oleg Sep 29 '10 at 10:57
  • 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) – Andrew Sep 29 '10 at 19:55
  • @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). – Oleg Sep 29 '10 at 21:00
  • @Oleg can you share library details for above solution. maven dependency details ? – Pruthvi Chitrala Apr 08 '17 at 11:41
  • @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). – Oleg Apr 08 '17 at 11:48
3

use this,

class MyDelete extends HttpPost{
    public MyDelete(String url){
        super(url);
    }
    @Override
    public String getMethod() {
        return "DELETE";
    }
}
Ishan Liyanage
  • 2,237
  • 1
  • 26
  • 25
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.

HopefullyHelpful
  • 1,652
  • 3
  • 21
  • 37