在Android中发送HTTP DELETE请求

时间:2022-11-21 20:09:44

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:

我的客户端API指定要删除对象,必须发送DELETE请求,其中包含描述内容的Json头数据。实际上它与添加对象的调用相同,这是通过POST完成的。这工作正常,我的代码的内容如下:

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:

为了发送删除请求,我将请求方法更改为“DELETE”。但是我收到以下错误:

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.

所以,我的问题是,如何从Android发送包含标题数据的DELETE请求?我错过了这一点 - 您是否能够将标题数据添加到DELETE请求中?谢谢。

9 个解决方案

#1


29  

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

有问题的行是con.setDoOutput(true);.删除它将修复错误。

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

您可以使用addRequestProperty或setRequestProperty将请求标头添加到DELETE,但无法添加请求正文。

#2


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().

getOutputStream()仅适用于具有正文的请求,如POST。在没有正文的请求(如DELETE)上使用它将抛出ProtocolException。相反,您应该使用addHeader()添加标头,而不是调用getOutputStream()。

#3


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");

#4


2  

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

这是旧版Android(<= 4.4)上HttpURLConnection的限制。

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.

虽然您可以选择使用HttpClient,但我不推荐它,因为它是一个旧的库,其中有几个问题已从Android 6中删除。

I would recommend using a new recent library like OkHttp:

我建议使用像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();
}

#5


2  

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

尝试下面的方法来调用HttpDelete方法,它对我有用,希望对你也有用

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();
        }

#6


1  

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".

DELETE请求是GET请求的扩展形式,根据android文档,您无法在DELETE请求的正文中写入。 HttpUrlConnection将抛出“无法写入协议异常”。

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

如果您仍想在正文中编写参数,我建议您使用OKHttp库。

OKHttp documentation

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

如果您有兴趣使用更简单的库,那么您可以尝试使用SimpleHttpAndroid库

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.

谢谢,希望它可能有所帮助。

#7


0  

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

你不能只使用addHeader()方法吗?

#8


0  

Here is my Delete request method.

这是我的删除请求方法。

Simply it is post request with extra RequestProperty

简单来说,它是带有额外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.

我希望它有所帮助。

#9


-7  

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

为了向这个问题添加闭包,发现没有受支持的方法来发送包含头数据的HTTP DELETE请求。

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.

解决方案是客户端更改其API以接受标准GET请求,该请求指示该操作应该是删除,包含要删除的项的ID。

http://clienturl.net/api/delete/id12345

#1


29  

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

有问题的行是con.setDoOutput(true);.删除它将修复错误。

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

您可以使用addRequestProperty或setRequestProperty将请求标头添加到DELETE,但无法添加请求正文。

#2


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().

getOutputStream()仅适用于具有正文的请求,如POST。在没有正文的请求(如DELETE)上使用它将抛出ProtocolException。相反,您应该使用addHeader()添加标头,而不是调用getOutputStream()。

#3


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");

#4


2  

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

这是旧版Android(<= 4.4)上HttpURLConnection的限制。

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.

虽然您可以选择使用HttpClient,但我不推荐它,因为它是一个旧的库,其中有几个问题已从Android 6中删除。

I would recommend using a new recent library like OkHttp:

我建议使用像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();
}

#5


2  

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

尝试下面的方法来调用HttpDelete方法,它对我有用,希望对你也有用

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();
        }

#6


1  

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".

DELETE请求是GET请求的扩展形式,根据android文档,您无法在DELETE请求的正文中写入。 HttpUrlConnection将抛出“无法写入协议异常”。

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

如果您仍想在正文中编写参数,我建议您使用OKHttp库。

OKHttp documentation

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

如果您有兴趣使用更简单的库,那么您可以尝试使用SimpleHttpAndroid库

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.

谢谢,希望它可能有所帮助。

#7


0  

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

你不能只使用addHeader()方法吗?

#8


0  

Here is my Delete request method.

这是我的删除请求方法。

Simply it is post request with extra RequestProperty

简单来说,它是带有额外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.

我希望它有所帮助。

#9


-7  

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

为了向这个问题添加闭包,发现没有受支持的方法来发送包含头数据的HTTP DELETE请求。

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.

解决方案是客户端更改其API以接受标准GET请求,该请求指示该操作应该是删除,包含要删除的项的ID。

http://clienturl.net/api/delete/id12345