web-dev-qa-db-fra.com

HttpDelete avec le corps

J'essaie d'utiliser un objet HttpDelete pour appeler la méthode delete d'un service Web. Le code du service Web analyse JSON du corps du message. Cependant, je ne comprends pas comment ajouter un corps à un objet HttpDelete. Y a-t-il un moyen de faire cela?

Avec HttpPut et HttpPost, j'appelle la méthode setEntity et lui transmet mon code JSON. Il ne semble pas que de telles méthodes existent pour HttpDelete.

S'il n'y a aucun moyen de définir un corps pour un objet HttpDelete, pourriez-vous me lier à une ressource qui utilise une super classe de HttpDelete telle que je puisse définir la méthode (delete) et définir un corps. Je sais que ce n'est pas idéal, mais pour le moment, je ne peux pas modifier le service Web.

40
Andrew

Avez-vous essayé de remplacer HttpEntityEnclosingRequestBase comme suit:

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

Cela créera un sosie HttpDelete- qui a une méthode setEntity. Je pense que la classe abstraite fait presque tout pour vous, alors c'est peut-être tout ce dont vous avez besoin.

FWIW, le code est basé sur cette source à HttpPost que Google a retournée .

91
Walter Mundt

En suivant les conseils de Walter Mudnt, vous pouvez utiliser ce code. Cela fonctionne, je viens de le faire en testant mon _service Web 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();
    }

Pour accéder à la réponse, vous pouvez simplement faire: response.getStatusLine();

9
dazito

Il existe différentes interprétations dans la question de savoir si le corps est autorisé ou non dans la requête HTTP DELETE. Voir this par exemple. Dans la spécification HTTP 1.1 il n'est pas explicitement interdit. À mon avis, vous ne devriez pas utiliser body dans le HTTP DELETE.

Néanmoins, je pense que vous devriez utiliser une URL telle que mysite/myobject/objectId (shop.com/order/1234) où objectId ( une partie de l'URL ) représente l'information supplémentaire. Vous pouvez également utiliser Paramètres URL : mysite/myobject?objectName=table&color=red pour envoyer des informations supplémentaires au serveur dans la requête HTTP DELETE. La partie commençant par '?' est le urlencoded paramètres divisés dy '&'.

Si vous souhaitez envoyer des informations plus complexes, vous pouvez convertir les données au format JSON en respectant DataContractJsonSerializer ou JavaScriptSerializer puis envoyer les données converties (une chaîne que je nomme myJsonData ultérieurement) également en tant que paramètre: mysite/myobject?objectInfo=myJsonData .

Si vous devez envoyer trop de données supplémentaires dans le cadre de la requête HTTP DELETE pour que vous ayez un problème de longueur d'URL, vous devriez probablement mieux modifier la conception de votre application.

UPDATED: Si vous voulez envoyer un corps par HTTP DELETE, vous pouvez le faire, par exemple, comme suit

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

le code complet pourrait être un peu plus complexe, mais celui-ci fonctionnera déjà. Néanmoins, je continue à dire que les données nécessaires au service Web dans le corps de la requête HTTP DELETE sont mal conçues.

4
Oleg

utilisez ceci,

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

en rattrapage 

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

vous devez déclencher une condition, via quelque chose et potentiellement faire un filtrage pour que l'url/l'en-tête/le corps supprime le déclencheur,

sauf si l'URL/corps/en-tête de suppression est suffisamment unique pour ne pas entrer en conflit avec post ou obtenir des demandes.

0
HopefullyHelpful