Sending HTTP DELETE request in Android
Asked Answered
M

9

29

My client's API specifies that to remove an object, a DELETE request must be sent, containing Json header data describing the content. Effectively it's the same call as adding an object, which is done via POST. This works fine, the guts of my code is below:

HttpURLConnection con = (HttpURLConnection)myurl.openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
con.setUseCaches(false);
con.connect();
OutputStreamWriter wr = new OutputStreamWriter(con.getOutputStream());
wr.write(data); // data is the post data to send
wr.flush();

To send the delete request, I changed the request method to "DELETE" accordingly. However I get the following error:

java.net.ProtocolException: DELETE does not support writing

So, my question is, how do I send a DELETE request containing header data from Android? Am I missing the point - are you able to add header data to a DELETE request? Thanks.

Mokpo answered 26/4, 2012 at 17:44 Comment(0)
P
33

The problematic line is con.setDoOutput(true);. Removing that will fix the error.

You can add request headers to a DELETE, using addRequestProperty or setRequestProperty, but you cannot add a request body.

Policlinic answered 11/5, 2013 at 12:57 Comment(3)
As often seen here on SO, the only correct answer is not elected and has no upvotes :(Abortive
What if I need send some json with DELETE?Joappa
@konopko or send it as part of the Url or as a headerBudget
S
7

This is a limitation of HttpURLConnection, on old Android versions (<=4.4).

While you could alternatively use HttpClient, I don't recommend it as it's an old library with several issues that was removed from Android 6.

I would recommend using a new recent library like OkHttp:

OkHttpClient client = new OkHttpClient();
Request.Builder builder = new Request.Builder()
    .url(getYourURL())
    .delete(RequestBody.create(
        MediaType.parse("application/json; charset=utf-8"), getYourJSONBody()));

Request request = builder.build();

try {
    Response response = client.newCall(request).execute();
    String string = response.body().string();
    // TODO use your response
} catch (IOException e) {
    e.printStackTrace();
}
Subalternate answered 11/7, 2016 at 22:29 Comment(0)
E
4

getOutputStream() only works on requests that have a body, like POST. Using it on requests that don't have a body, like DELETE, will throw a ProtocolException. Instead, you should add your headers with addHeader() instead of calling getOutputStream().

Epiphysis answered 26/4, 2012 at 17:56 Comment(1)
I don't see a addHeader() method in java.net.HttpURLConnection - what method are you referring to?Mokpo
T
4

I know is a bit late, but if anyone falls here searching on google like me I solved this way:

    conn.setRequestProperty("X-HTTP-Method-Override", "DELETE");
    conn.setRequestMethod("POST");
Testimony answered 27/2, 2016 at 0:22 Comment(2)
Thanks! This problem makes me crazy, but your solution helpsArchipenko
This only works if your server is configured to use that custom header. It is common but not standard. Some server side API frameworks will see the header and go, "oh, okay, this is actually a delete method, but they are using POST". You could program this behavior yourself.Cirilo
A
4

DELETE request is an extended form of GET request, as per the android documentation you cannot write in the body of DELETE request. HttpUrlConnection will throw "unable to write protocol exception".

If you still want to write the parameter in the body, i suggest you to use the OKHttp Library.

OKHttp documentation

If you are intrested to use more simpler library then you can try SimpleHttpAndroid library

One thing to remember here is if you are not writing anything in the body then remove the line

conn.setDoOutput(true);

Thanks, Hopefully it may help.

Adulterine answered 10/7, 2017 at 10:43 Comment(0)
O
1

Try below method for call HttpDelete method, it works for me, hoping that work for you as well

String callHttpDelete(String url){

             try {
                    HttpParams httpParams = new BasicHttpParams();
                    HttpConnectionParams.setConnectionTimeout(httpParams, 15000);
                    HttpConnectionParams.setSoTimeout(httpParams, 15000);

                    //HttpClient httpClient = getNewHttpClient();
                    HttpClient httpClient = new DefaultHttpClient();// httpParams);


                    HttpResponse response = null;    
                    HttpDelete httpDelete = new HttpDelete(url);    
                    response = httpClient.execute(httpDelete); 

                    String sResponse;

                    StringBuilder s = new StringBuilder();

                    while ((sResponse = reader.readLine()) != null) {
                        s = s.append(sResponse);
                    }

                    Log.v(tag, "Yo! Response recvd ["+s.toString()+"]");
                    return s.toString();
                } catch (Exception e){
                    e.printStackTrace();
                }
              return s.toString();
        }
Oud answered 13/5, 2015 at 8:18 Comment(1)
What is "final_url"? Did you mean "url"? And where do you write additional data to the request? I can't see any connection to the question.Simplehearted
A
0

You can't just use the addHeader() method?

Abraham answered 26/4, 2012 at 17:47 Comment(4)
As asked above, what addHeader() method are you suggesting? Two answers to my question seem to suggest the same method, but unless I'm missing something that method doesn't exist.Mokpo
Looks like your missing it to be, look at HTTPURLConnection's parent.URLConnectionAbraham
That method is addRequestHeader(), which is not the same as addHeader()..!Mokpo
Edit: That method is addRequestProperty(String field, String newValue) (so not the same as addHeader() )... Also, it requires that I give my data a name - the original code flushes the data without any such name, so I'm not sure how I can use this to achieve the same resultMokpo
M
0

Here is my Delete request method.

Simply it is post request with extra RequestProperty

connection.setRequestProperty("X-HTTP-Method-Override", "DELETE");

Below the complete method.

    public void executeDeleteRequest(String stringUrl, JSONObject jsonObject, String reqContentType, String resContentType, int timeout) throws Exception {
    URL url = new URL(stringUrl);
    HttpURLConnection connection = null;
    String urlParameters = jsonObject.toString();
    try {
        connection = (HttpURLConnection) url.openConnection();

        //Setting the request properties and header
        connection.setRequestProperty("X-HTTP-Method-Override", "DELETE");
        connection.setRequestMethod("POST");
        connection.setRequestProperty("User-Agent", USER_AGENT);
        connection.setRequestProperty(CONTENT_TYPE_KEY, reqContentType);
        connection.setRequestProperty(ACCEPT_KEY, resContentType);


        connection.setReadTimeout(timeout);
        connection.setConnectTimeout(defaultTimeOut);

        connection.setUseCaches(false);
        connection.setDoInput(true);
        connection.setDoOutput(true);

        // Send request
        DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
        wr.writeBytes(urlParameters);
        wr.flush();
        wr.close();
        responseCode = connection.getResponseCode();
        // To handle web services which server responds with response code
        // only
        try {
            response = convertStreamToString(connection.getInputStream());
        } catch (Exception e) {
            Log.e(Log.TAG_REST_CLIENT, "Cannot convert the input stream to string for the url= " + stringUrl + ", Code response=" + responseCode + "for the JsonObject: " + jsonObject.toString(), context);
        }
    } catch (
            Exception e
            )

    {
        if (!BController.isInternetAvailable(context)) {
            IntentSender.getInstance().sendIntent(context, Constants.BC_NO_INTERNET_CONNECTION);
            Log.e(Log.TAG_REST_CLIENT, "No internet connection", context);
        }
        Log.e(Log.TAG_REST_CLIENT, "Cannot perform the POST request successfully for the following URL: " + stringUrl + ", Code response=" + responseCode + "for the JsonObject: " + jsonObject.toString(), context);
        throw e;
    } finally{

        if (connection != null) {
            connection.disconnect();
        }
    }

}

I hope it helped.

Minnie answered 5/9, 2016 at 20:52 Comment(0)
M
-7

To add closure to this question, it transpired that there is no supported method to send an HTTP DELETE request containing header data.

The solution was for the client to alter their API to accept a standard GET request which indicated that the action should be a delete, containing the id of the item to be deleted.

http://clienturl.net/api/delete/id12345
Mokpo answered 26/1, 2013 at 12:16 Comment(4)
This answer is inaccurate. You CAN add header data, just not a body. The problem is when you call setDoOutput(true).Policlinic
Changing the method to GET is the worst thing you could do.Abortive
making a GET request to replace your DELETE request is NOT a good practice at all. Later on it will lead you into further problems.Steamy
it easy to mark ones reply a an answer even though it´s incorrect. you should unmark this before you break down vote record cheers!Budget

© 2022 - 2024 — McMap. All rights reserved.