2010-09-22 39 views
38

Estoy intentando utilizar un objeto HttpDelete para invocar el método de eliminación de un servicio web. El código del servicio web analiza JSON desde el cuerpo del mensaje. Sin embargo, no estoy logrando entender cómo agregar un cuerpo a un objeto HttpDelete. ¿Hay alguna forma de hacer esto?HttpDelete con cuerpo

Con HttpPut y HttpPost, llamo al método setEntity y paso en mi JSON. No parece haber ningún método de este tipo para HttpDelete.

Si no hay forma de configurar un cuerpo para un objeto HttpDelete, ¿podría vincularme a un recurso que utiliza una superclase de HttpDelete para que pueda establecer el método (eliminar) y establecer un cuerpo. Sé que no es ideal, pero en este momento no puedo modificar el servicio web.

Respuesta

86

has necesitado anulando HttpEntityEnclosingRequestBase de la siguiente manera:

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

que creará una HttpDelete -lookalike que tiene un método setEntity. Creo que la clase abstracta hace casi todo por ti, por lo que puede ser todo lo que se necesita.

FWIW, el código se basa en this source to HttpPost that Google turned up.

+4

¡Eres un tipo! ¡Gracias! –

+0

¡Uf! Esto no parece funcionar con HttpURLConnection. Me aparece "java.net.ProtocolException: DELETE no admite escritura". http://stackoverflow.com/questions/10338615/sending-http-delete-request-in-android –

+0

Estoy con Scott ... ¿cómo hago esto con HttpURLConnection? Tengo que volver a escribir mi código de red para usar Apache HTTP? –

4

Existen diferentes interpretaciones en la pregunta si el cuerpo está permitido o no en la solicitud HTTP DELETE. Ver this por ejemplo. En el HTTP 1.1 specification no está explícitamente prohibido. En mi opinión, no debe usar el cuerpo en el HTTP DELETE.

Nevertherless creo que se debe utilizar URL como mysite/myobject/objectId (shop.com/order/1234) donde el objectId (una parte de la url) es la información adicional. Como alternativa, puede usar Parámetros de URL: mysite/myobject?objectName=table&color=red para enviar información adicional al servidor en la solicitud HTTP DELETE. La parte que comienza con '?' es el urlencoded parámetros divididos dy '&'.

Si desea enviar información más compleja que puede convertir los datos a JSON con respecto a DataContractJsonSerializer o JavaScriptSerializer y luego enviar los datos convertidos (una cadena que nombro myJsonData más adelante) también como el parámetro: mysite/myobject?objectInfo=myJsonData.

Si necesita enviar demasiados datos adicionales como parte de la solicitud HTTP DELETE para que tenga problemas con la longitud de la URL, entonces probablemente debería cambiar el diseño de su aplicación.

ACTUALIZADO: Iy usted quiere enviar alguna corporal por DELETE HTTP se puede hacer esto, por ejemplo, como seguir

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

el código completo podría ser un poco más complejo, pero éste ya se va a trabajar. Sin embargo, sigo diciendo que el servicio web necesitaba datos en el cuerpo de la solicitud HTTP DELETE mal diseñados.

+1

-1. El interlocutor dijo claramente que no puede cambiar el servicio web, y probablemente tampoco lo diseñó. Dado que cada recomendación en esta publicación implica cambiar el código que no está bajo el control del solicitante, es completamente inútil en la situación en cuestión. –

+0

Por lo que vale, no estoy en desacuerdo con sus puntos por principio; un servicio web que requiera métodos DELETE con un cuerpo probablemente esté mal diseñado. No obstante, es legítimo preguntar cómo interactuar con un servicio web mal diseñado y posiblemente no conforme con las normas, y así es como interpreto esta pregunta. –

+0

@Walter Mundt: Si uno ** do ** necesita enviar cuerpo en HTTP DELETE, agregué un ejemplo con una de las formas posibles de hacerlo. – Oleg

3

uso esto,

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

Siguiendo el consejo Walter Mudnt, puede utilizar este código. Funciona, lo hice mientras probaba mi servicio 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(); 
    } 

Para acceder a la respuesta puede simplemente hacer: response.getStatusLine();

+1

Gracias hombre, eres rockero :) –

0

en retrofit

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

tiene que desencadenar estado, a través de algo y llegar a tener que hacer algún tipo de filtrado para la url/cabecera/body para eliminar el activador,

a menos que la URL eliminada/cuerpo/encabezado sea lo suficientemente única como para no colisionar con la publicación u obtener solicitudes.

Cuestiones relacionadas