带正文的 HttpDelete
Posted
技术标签:
【中文标题】带正文的 HttpDelete【英文标题】:HttpDelete with body 【发布时间】:2010-09-22 20:25:55 【问题描述】:我正在尝试使用 HttpDelete 对象来调用 Web 服务的删除方法。 Web 服务的代码从消息的正文中解析 JSON。但是,我不明白如何将正文添加到 HttpDelete 对象。有没有办法做到这一点?
使用 HttpPut 和 HttpPost,我调用 setEntity 方法并传入我的 JSON。 HttpDelete 似乎没有任何此类方法。
如果无法为 HttpDelete 对象设置主体,请您将我链接到使用 HttpDelete 超类的资源,以便我可以设置方法(删除)并设置主体。我知道这并不理想,但此时我无法更改网络服务。
【问题讨论】:
【参考方案1】:您是否尝试过如下覆盖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();
这将创建一个具有setEntity
方法的HttpDelete
-lookalike。我认为抽象类几乎可以为您完成所有工作,所以这可能就是您所需要的。
FWIW,代码基于this source to HttpPost that Google turned up。
【讨论】:
呃!这似乎不适用于 HttpURLConnection。我收到“java.net.ProtocolException:DELETE 不支持写入”。 ***.com/questions/10338615/… 我和 Scott 在一起......我如何使用 HttpURLConnection 做到这一点?我必须重写我的网络代码才能使用 Apache HTTP? 不可能有带有 HttpURLConnection 的正文的 DELETE。我需要它,我最终使用了 HttpClient。【参考方案2】:按照 Walter Mudnt 的建议,您可以使用此代码。它有效,只是在测试我的 REST 网络服务时成功。
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();
【讨论】:
【参考方案3】:HTTP DELETE
请求中是否允许正文的问题有不同的解释。例如,请参阅this。在HTTP 1.1 specification 中没有明确禁止。在我看来,您不应该在HTTP DELETE
中使用正文。
尽管如此,我认为您应该使用像 mysite/myobject/objectId
(shop.com/order/1234
) 这样的 URL,其中 objectId
(url 的一部分)是附加信息。作为替代方案,您可以使用 URL 参数:mysite/myobject?objectName=table&color=red
在HTTP DELETE
请求中向服务器发送附加信息。以“?”开头的部分是 urlencoded 参数分隔 dy '&'。
如果您想发送更复杂的信息,您可以将数据转换为关于 DataContractJsonSerializer 或 javascriptSerializer 的 JSON,然后将转换后的数据(我稍后命名为 myJsonData
的字符串)也作为参数发送: mysite/myobject?objectInfo=myJsonData
.
如果您需要在 HTTP DELETE
请求中发送过多的附加数据,从而导致 URL 长度出现问题,那么您最好更改应用程序的设计。
已更新:如果您确实希望通过 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 请求正文中的数据设计不佳。
【讨论】:
-1。提问者说的很清楚,他不能改变网络服务,而且他可能也没有设计它。由于这篇文章中的每条建议都涉及更改不受提问者控制的代码,因此在手头的情况下完全没有帮助。 对于它的价值,我原则上不同意你的观点;需要带有主体的 DELETE 方法的 Web 服务可能设计不佳。尽管如此,询问如何与设计不佳且可能不符合标准的 Web 服务交互是合理的,这就是我对这个问题的解释。 @Walter Mundt:如果一个确实需要在 HTTP DELETE 中发送正文,我添加了一个示例,其中一种可能的方法是。 我能问一下为什么有一个带有删除方法的主体不是一个好主意吗?仅仅是因为人们通常不这样做吗?当然可以;那么这是一个坏主意的原因是什么? (我没有不同意。我只是在询问。我是网络服务的新手) @Andrew:大多数HTTP库类等的实现都认为DELETE应该没有body。在这种情况下,必须有一个 非常好的 理由来设计具有此功能的 wen 服务的实现。大多数情况下,在 RESTful 服务中不使用 HTTP DELETE。在 REST 中,url 应该标识资源,因此 HTTP DELETE 包含有关应该在 在 URL 中删除的对象的所有信息。不禁止使用带参数的 HTTP GET 来更改资源或使用 HTTP PUT 来删除资源,但这会是一种糟糕的风格(糟糕的设计)。【参考方案4】:使用这个,
class MyDelete extends HttpPost
public MyDelete(String url)
super(url);
@Override
public String getMethod()
return "DELETE";
【讨论】:
【参考方案5】:改造中
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 进行一些过滤以删除触发器,
除非删除 url/body/header 足够独特,不会与 post 或 get 请求发生冲突。
【讨论】:
以上是关于带正文的 HttpDelete的主要内容,如果未能解决你的问题,请参考以下文章
使用Retrofit(Okhttp)时如何从android studio中的log cat复制请求正文,标头(不带标签)?
在调用gmail api发送带附件的电子邮件(multipart)时,请求的正文如何?
[Java] JavaMail 发送带图片的 html 格式的邮件