Http удалить с тела - PullRequest
       12

Http удалить с тела

40 голосов
/ 23 сентября 2010

Я пытаюсь использовать объект HttpDelete для вызова метода удаления веб-службы. Код веб-службы анализирует JSON из тела сообщения. Однако я не понимаю, как добавить тело к объекту HttpDelete. Есть ли способ сделать это?

С помощью HttpPut и HttpPost я вызываю метод setEntity и передаю свой JSON. Похоже, для HttpDelete такого метода не существует.

Если нет способа установить тело для объекта HttpDelete, не могли бы вы связать меня с ресурсом, который использует суперкласс HttpDelete, чтобы я мог установить метод (удалить) и установить тело. Я знаю, что это не идеально, но на данный момент я не могу изменить веб-сервис.

Ответы [ 5 ]

91 голосов
/ 29 сентября 2010

Вы пытались переопределить 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, код основан на этом источнике для HttpPost, который Google обнаружил .

9 голосов
/ 10 апреля 2014

Следуя совету Уолтера Маднта, вы можете использовать этот код.Это работает, только что сделал это во время тестирования моего веб-сервиса 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();

4 голосов
/ 29 сентября 2010

Существуют различные толкования в вопросе, разрешено ли тело в запросе HTTP DELETE.См. this например.В спецификации HTTP 1.1 это явно не запрещено.По моему мнению, вы не должны использовать тело в HTTP DELETE.

Тем не менее я думаю, что вы должны использовать URL-адрес, такой как mysite/myobject/objectId (shop.com/order/1234), где objectId ( часть url ) является дополнительной информацией.В качестве альтернативы вы можете использовать параметры URL : mysite/myobject?objectName=table&color=red для отправки дополнительной информации на сервер в запросе HTTP DELETE.Часть, начинающаяся с '?'это urlencoded параметры, разделенные dy '&'.

Если вы хотите отправить более сложную информацию, вы можете преобразовать данные в JSON с учетом DataContractJsonSerializer или JavaScriptSerializer , а затем отправьте преобразованные данные (строку, которую я позже назову myJsonData) также в качестве параметра: mysite/myobject?objectInfo=myJsonData.

Если вам необходимо отправить слишком много дополнительных данных в составеHTTP DELETE запросите, чтобы у вас были проблемы с длиной URL, тогда вам, вероятно, лучше изменить дизайн вашего приложения.

ОБНОВЛЕНО : То есть вы действительно хотите отправить какое-то тело за HTTP УДАЛИТЬ васнапример, можно выполнить, например, следующий

// 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, он плохо спроектирован.

3 голосов
/ 06 июня 2013

используйте это,

class MyDelete extends HttpPost{
    public MyDelete(String url){
        super(url);
    }
    @Override
    public String getMethod() {
        return "DELETE";
    }
}
0 голосов
/ 06 января 2017

в модификации

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 / заголовка / тела для удаления триггера,

, если только удалениеurl / body / header достаточно уникален, чтобы не конфликтовать с постом или получать запросы.

...