2012-04-26 22 views
22

La API de mi cliente especifica que para eliminar un objeto, se debe enviar una solicitud DELETE, que contenga datos del encabezado Json que describan el contenido. Efectivamente, es la misma llamada que agregar un objeto, que se realiza a través de POST. Esto funciona bien, las tripas de mi código es el siguiente:Enviando solicitud HTTP DELETE en Android

HttpURLConnection con = (HttpURLConnection)myurl.openConnection(); 
con.setRequestMethod("POST"); 
con.setDoOutput(true); 
con.setUseCaches(false); 
con.connect(); 
OutputStreamWriter wr = new OutputStreamWriter(con.getOutputStream()); 
wr.write(data); // data is the post data to send 
wr.flush(); 

para enviar la solicitud de eliminación, he cambiado el método de la petición de "BORRAR" en consecuencia. Sin embargo, me sale el siguiente error:

java.net.ProtocolException: DELETE does not support writing 

lo tanto, mi pregunta es, ¿Cómo se envía una solicitud DELETE que contiene datos de cabecera de Android? ¿Me falta el punto? ¿Puedes agregar datos de encabezado a una solicitud DELETE? Gracias.

Respuesta

-6

Para agregar cierre a esta pregunta, resultó que no hay un método compatible para enviar una solicitud HTTP DELETE que contenga datos de encabezado.

La solución fue que el cliente modificara su API para aceptar una solicitud GET estándar que indicaba que la acción debería ser una eliminación, que contiene el id del elemento que se eliminará.

http://clienturl.net/api/delete/id12345 
+2

Esta respuesta no es precisa. PUEDE agregar datos de encabezado, simplemente no un cuerpo. El problema es cuando llamas a 'setDoOutput (true)'. – TalkLittle

+5

Cambiar el método a GET es lo peor que podría hacer. – hgoebl

+0

hacer una solicitud GET para reemplazar su solicitud DELETE NO es una buena práctica en absoluto. Más tarde te llevará a más problemas. – dazito

0

No puede simplemente usar el método addHeader()?

+1

Como se preguntó anteriormente, ¿qué método addHeader() estás sugiriendo? Dos respuestas a mi pregunta parecen sugerir el mismo método, pero a menos que me falta algo, ese método no existe. – androidneil

+0

Parece que falta, mira el padre 'HTTPURLConnection'. [' URLConnection'] (http://bit.ly/Jkja7G) – hwrdprkns

+1

Ese método es addRequestHeader(), que no es lo mismo que addHeader () ..! – androidneil

4

getOutputStream() solo funciona en solicitudes que tienen un cuerpo, como POST. Al usarlo en solicitudes que no tienen un cuerpo, como DELETE, lanzará una ProtocolException. En su lugar, debe agregar sus encabezados con addHeader() en lugar de llamar a getOutputStream().

+1

No veo un método addHeader() en java.net.HttpURLConnection - ¿A qué método se refiere? – androidneil

27

La línea problemática es con.setDoOutput(true);. Eliminar eso solucionará el error.

Puede agregar encabezados de solicitud a un DELETE, usando addRequestProperty o setRequestProperty, pero no puede agregar un cuerpo de solicitud.

+0

Como se ve a menudo aquí en SO, la única respuesta correcta no es elegida y no tiene votos ascendentes :( – hgoebl

+0

¿Qué pasa si necesito enviar un json con ELIMINAR? –

+0

@konopko o enviarlo como parte de la Url o como encabezado –

2

Try a continuación el método para la llamada HttpDelete método, que funciona para mí, con la esperanza de que el trabajo para usted, así

String callHttpDelete(String url){ 

      try { 
        HttpParams httpParams = new BasicHttpParams(); 
        HttpConnectionParams.setConnectionTimeout(httpParams, 15000); 
        HttpConnectionParams.setSoTimeout(httpParams, 15000); 

        //HttpClient httpClient = getNewHttpClient(); 
        HttpClient httpClient = new DefaultHttpClient();// httpParams); 


        HttpResponse response = null;  
        HttpDelete httpDelete = new HttpDelete(url);  
        response = httpClient.execute(httpDelete); 

        String sResponse; 

        StringBuilder s = new StringBuilder(); 

        while ((sResponse = reader.readLine()) != null) { 
         s = s.append(sResponse); 
        } 

        Log.v(tag, "Yo! Response recvd ["+s.toString()+"]"); 
        return s.toString(); 
       } catch (Exception e){ 
        e.printStackTrace(); 
       } 
       return s.toString(); 
     } 
+0

¿Qué es? "final_url"? ¿Querías decir "url"? ¿Y dónde escribes datos adicionales a la solicitud? No puedo ver ninguna conexión con la pregunta. –

+0

sí url, Gracias por actualizarme el error de texto ... – Lokesh

4

Sé que es un poco tarde, pero si alguien se cae aquí en busca de Google como yo he resuelto de esta manera:

conn.setRequestProperty("X-HTTP-Method-Override", "DELETE"); 
    conn.setRequestMethod("POST"); 
+0

¡Gracias! Este problema me vuelve loco, pero tu solución ayuda a – XXX

+1

Esto no funcionó para mí. – Murphy

+0

Me funcionó –

2

ésta es una limitación de HttpURLConnection, en las antiguas versiones de Android (< = 4,4).

Mientras que usted podría utilizar alternativamente HttpClient, yo no lo recomiendo ya que es una antigua biblioteca con varios problemas que era removed from Android 6.

Yo recomendaría el uso de una nueva biblioteca recientes como OkHttp:

OkHttpClient client = new OkHttpClient(); 
Request.Builder builder = new Request.Builder() 
    .url(getYourURL()) 
    .delete(RequestBody.create(
     MediaType.parse("application/json; charset=utf-8"), getYourJSONBody())); 

Request request = builder.build(); 

try { 
    Response response = client.newCall(request).execute(); 
    String string = response.body().string(); 
    // TODO use your response 
} catch (IOException e) { 
    e.printStackTrace(); 
} 
0

Aquí es mi método Delete petición.

Simplemente es post solicitud adicional con RequestProperty

connection.setRequestProperty("X-HTTP-Method-Override", "DELETE"); 

Debajo del método completo.

public void executeDeleteRequest(String stringUrl, JSONObject jsonObject, String reqContentType, String resContentType, int timeout) throws Exception { 
    URL url = new URL(stringUrl); 
    HttpURLConnection connection = null; 
    String urlParameters = jsonObject.toString(); 
    try { 
     connection = (HttpURLConnection) url.openConnection(); 

     //Setting the request properties and header 
     connection.setRequestProperty("X-HTTP-Method-Override", "DELETE"); 
     connection.setRequestMethod("POST"); 
     connection.setRequestProperty("User-Agent", USER_AGENT); 
     connection.setRequestProperty(CONTENT_TYPE_KEY, reqContentType); 
     connection.setRequestProperty(ACCEPT_KEY, resContentType); 


     connection.setReadTimeout(timeout); 
     connection.setConnectTimeout(defaultTimeOut); 

     connection.setUseCaches(false); 
     connection.setDoInput(true); 
     connection.setDoOutput(true); 

     // Send request 
     DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); 
     wr.writeBytes(urlParameters); 
     wr.flush(); 
     wr.close(); 
     responseCode = connection.getResponseCode(); 
     // To handle web services which server responds with response code 
     // only 
     try { 
      response = convertStreamToString(connection.getInputStream()); 
     } catch (Exception e) { 
      Log.e(Log.TAG_REST_CLIENT, "Cannot convert the input stream to string for the url= " + stringUrl + ", Code response=" + responseCode + "for the JsonObject: " + jsonObject.toString(), context); 
     } 
    } catch (
      Exception e 
      ) 

    { 
     if (!BController.isInternetAvailable(context)) { 
      IntentSender.getInstance().sendIntent(context, Constants.BC_NO_INTERNET_CONNECTION); 
      Log.e(Log.TAG_REST_CLIENT, "No internet connection", context); 
     } 
     Log.e(Log.TAG_REST_CLIENT, "Cannot perform the POST request successfully for the following URL: " + stringUrl + ", Code response=" + responseCode + "for the JsonObject: " + jsonObject.toString(), context); 
     throw e; 
    } finally{ 

     if (connection != null) { 
      connection.disconnect(); 
     } 
    } 

} 

Espero que haya sido de ayuda.

1

La solicitud DELETE es una forma extendida de solicitud GET, según la documentación de Android que no puede escribir en el cuerpo de la solicitud DELETE. HttpUrlConnection lanzará "no se puede escribir la excepción de protocolo".

Si aún desea escribir el parámetro en el cuerpo, le sugiero que utilice la biblioteca OKHttp.

OKHttp documentation

Si estás quiera usar más biblioteca simple entonces usted puede intentar SimpleHttpAndroid library

Una cosa a recordar aquí es que si usted no está escribiendo algo en el cuerpo, entonces, eliminar la línea

conn.setDoOutput(true); 

Gracias, con un poco de suerte, puede ayudar.