HttpDelete с телом
Я пытаюсь использовать объект HttpDelete для вызова метода удаления веб-службы. Код веб-службы анализирует 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(); }
}
Это создаст HttpDelete
-lookalike, который имеет метод setEntity
. Я думаю, что абстрактный класс делает почти все для вас, так что это может быть все, что нужно.
FWIW, код основан на этом источнике на HttpPost, который Google появился.
Ответ 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
, существует другая интерпретация. См. этот. В спецификация HTTP 1.1 она явно не запрещена. По-моему, вы не должны использовать тело в HTTP DELETE
.
Neverlessless Я думаю, что вы должны использовать URL, например mysite/myobject/objectId
(shop.com/order/1234
), где дополнительная информация содержится в objectId
( части URL). В качестве альтернативы вы можете использовать параметры URL: mysite/myobject?objectName=table&color=red
для отправки дополнительной информации на сервер в запросе HTTP DELETE
. Часть, начинающаяся с '?' это urlencoded параметры devided dy '&'.
Если вы хотите отправить более сложную информацию, вы можете преобразовать данные в JSON в отношении DataContractJsonSerializer или JavaScriptSerializer, а затем отправить преобразованные данные (строка, которую я называю 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
полный код может быть немного сложнее, но этот уже будет работать. Тем не менее я продолжаю говорить, что веб-служба нуждается в данных в теле запроса HTTP DELETE, плохо спроектирована.
Ответ 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, чтобы удалить триггер,
если заголовок delete url/body/не будет уникальным, чтобы не столкнуться с сообщением или получить запросы.