HttpDelete与身体

时间:2010-09-22 20:25:56

标签: android httpclient webservice-client http-delete

我正在尝试使用HttpDelete对象来调用Web服务的delete方法。 Web服务的代码从消息的正文中解析JSON。但是,我无法理解如何向HttpDelete对象添加主体。有没有办法做到这一点?

使用HttpPut和HttpPost,我调用setEntity方法并传入我的JSON。 HttpDelete似乎没有任何此类方法。

如果无法为HttpDelete对象设置正文,请将我链接到使用超类HttpDelete的资源,以便我可以设置方法(删除)并设置正文。我知道这不太理想,但此时我无法改变网络服务。

5 个答案:

答案 0 :(得分:91)

您是否尝试过覆盖HttpEntityEnclosingRequestBase,如下所示:

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

这将创建HttpDelete - 具有setEntity方法的相似内容。我认为抽象类几乎可以为你做所有事情,所以这可能就是所需要的。

FWIW,代码基于this source to HttpPost that Google turned up

答案 1 :(得分:9)

根据Walter Mudnt的建议,您可以使用此代码。它可以正常运行,只需在测试我的REST Web服务时就可以实现。

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

要访问回复,您只需执行以下操作:response.getStatusLine();

答案 2 :(得分:4)

HTTP DELETE请求中是否允许正文的问题有不同的解释。例如,请参阅this。在HTTP 1.1 specification中没有明确禁止。在我看来,不应在HTTP DELETE中使用正文

Nevertherless我认为您应该使用mysite/myobject/objectIdshop.com/order/1234)之类的网址,其中objectId网址的一部分)是附加信息。作为替代方案,您可以使用网址参数mysite/myobject?objectName=table&color=redHTTP DELETE请求中向服务器发送附加信息。以“?”开头的部分是urlencoded参数分配dy'&'。

如果要发送更复杂的信息,可以将数据转换为DataContractJsonSerializerJavaScriptSerializer的JSON,然后发送转换后的数据(我之后命名为myJsonData的字符串)也作为参数:mysite/myobject?objectInfo=myJsonData

如果您需要发送过多的附加数据作为HTTP DELETE请求的一部分,这样您就会遇到网址长度问题,那么您应该更好地更改应用程序的设计。

更新:您确实希望每个HTTP DELETE发送一些正文,您可以执行此操作,例如,如下所示

// 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

完整的代码可能会稍微复杂一点,但这个代码已经可以使用了。不过我继续说Web Service需要在HTTP DELETE请求体内的数据设计不好。

答案 3 :(得分:3)

使用此,

class MyDelete extends HttpPost{
    public MyDelete(String url){
        super(url);
    }
    @Override
    public String getMethod() {
        return "DELETE";
    }
}

答案 4 :(得分:0)

在改造中

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

你必须通过某些东西触发条件,并且可能必须对url / header / body进行一些过滤来移除触发器,

除非删除网址/正文/标题的唯一性足以不与帖子或获取请求发生冲突。