bad request 400 en retrofit

1,492 views
Skip to first unread message

edgar macas

unread,
Nov 18, 2015, 1:21:09 AM11/18/15
to desarrolladores-android
Saludos espero me puedan ayudar con el siguiente problema:
Estoy utilizando retrofit para acceder a un api, rest al momento de generar el @GET me funciona perfectamente pero al momento de realizarlo con el @POST este me arroja en el metodo "onResponse" los siguientes valores
response.body() = null
response.message = BAD REQUEST 400

he probado el método POST con "Postman" y si me lo crea, pero como lo mencione desde retrofit no me lo agrega.

este es el codigo que estoy utilizando para el metodo POST:

new Retrofit.Builder()
 
.baseUrl("http://myapirest/")
 
.addConverterFactory(GsonConverterFactory.create())
 
.build();
AlojamientoService servicio = retrofit.create(AlojamientoService.class);
EstablecimientoPublico publico= new EstablecimientoPublico("post", -79.097676, 4.987654, "ed...@gmail.com");
Call<EstablecimientoPublico> call = servicio.crearEstablecimiento(publico);
call
.enqueue(new Callback<EstablecimientoPublico>() {
 
@Override
 
public void onResponse(Response<EstablecimientoPublico> response, Retrofit retrofit) {
 
Log.e("body", String.valueOf(response.body()));
 
Log.e("message", String.valueOf(response.message()));
 
Log.e("code", String.valueOf(response.code()));
 
}
 
@Override
 
public void onFailure(Throwable t) {
 
Log.e("error", t.getMessage());
 
}
})

y la parte de mi interface
public interface AlojamientoService {
 
@GET("/categorias/1/")
 
Call<Alojamiento> getAlojamiento();

 
@Headers("Content-Type: application/json")
 
@POST("publicos/")
 
Call<EstablecimientoPublico> crearEstablecimiento(@Body EstablecimientoPublico publico);

}

Les agradesco cualquier ayuda...

Gilberto Cuba Ricardo

unread,
Nov 18, 2015, 8:10:31 AM11/18/15
to desarrollad...@googlegroups.com
Hola colega,

Por lo pronto decir que es difícil ayudarte sin una salida del
"logcat". Habilita en tu código el traceo de las peticiones con
retrofit de esta forma.

new Retrofit.Builder()
.baseUrl("http://myapirest/")
.setLogLevel(RestAdapter.LogLevel.FULL)
.addConverterFactory(GsonConverterFactory.create())
.build();

Entonces, por sospecha lo único que veo es que es extraño que no te
haya saltado como error que te falta un separador de slash delante en
la petición de POST; es decir, tienes en tu código:

@Headers("Content-Type: application/json")
@POST("publicos/")
Call<EstablecimientoPublico> crearEstablecimiento(@Body
EstablecimientoPublico publico);

cuando debería ser:

@Headers("Content-Type: application/json")
@POST("/publicos/")
Call<EstablecimientoPublico> crearEstablecimiento(@Body
EstablecimientoPublico publico);

Nótese el slash "/" delante de la palabra "publicos".

Ya nos contarás, y espero que resuelvas.

--
Saludos,
Gilberto Cuba

Eduardo Martin Cabrera

unread,
Nov 18, 2015, 9:02:27 AM11/18/15
to desarrollad...@googlegroups.com
bueno si funciona con postman entonces el servicio REST debe andar ok, solo falta ver que es lo que esta enviando la app 

Recomendación #1:
  • en tus interfaces donde definís los endpoints seguí la norma, solo usa la barra al comienzo y no al final de los paths
  • en getAlojamiento estas usando barra al final, y en crearEstablecimiento no estas usando barra al comienzo y estas usando barra al final
  • en la cadena de la url que estés usando como base de tu api (la cadena que le das como parámetro al  metodo baseUrl() ) no uses barra al final
  • Duda, en crearEstablecimiento deberia ir el annotation @Headers("Content-Type: application/json") ? no creo que perjudique en la petición, pero me parece que sobra, salvo que el service rest dependa de este header enviado por el cliente y si esta presente con ese valor entonces modificara la salida para devolver un json de respuesta, pero es mas bien una duda mia nomas.

Recomendación #2:
en retrofit se puede activar un interceptor (del la lib okhttp que usa retrofit para hacer las peticiones) y vuelca un logging de las peticiones (que por defecto esta desactivado) hacia el android studio, la forma en que se hace varia segun que version de retrofit se use y puede llevar mas trabajo en la 2 (hay que agregar un repo maven al build.gradle es todo un tema eso), la idea seria que logres setear el nivel de debug en HEADER o BODY para obtener mas datos


https://futurestud.io/blog/retrofit-using-the-log-level-to-debug-requests/ 

asi con eso poder ver que el método de la peticion sea POST, la url sea la correcta y ver como se envía el parámetro, esto te muestra en a.studio de manera muy piola todos los datos de las peticiones 

Recomendación #2 alternativa:
quizás requiere un poco de trabajo, pero es otra manera de espiar la peticiones con http://facebook.github.io/stetho/
que ademas te permite ver otras cosas como db sqlite, etc y esta bastante recomendable, se integra con chrome para la visualización


Eduardo Martin Cabrera

unread,
Nov 18, 2015, 9:12:38 AM11/18/15
to desarrollad...@googlegroups.com
Hola, sin animo de entrar en polemicas pero me parece que ese .setLogLevel(RestAdapter.LogLevel.FULL) no le sirve si esta usando retrofit 2, si esta usando R2 :p entonces tiene habilitar el loglevel desde el cliente http (juro que esos cambios de timón de los developers de librerias me afectan mucho) , por eso seria bueno que ademas nos pase que versión exacta de retrofit esta usando, saludos

Editado:
para retrofit 2

        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
// set your desired log level
logging.setLevel(HttpLoggingInterceptor.Level.HEADERS);

OkHttpClient httpClient = new OkHttpClient();
// add your other interceptors …

// add logging as last interceptor
httpClient.interceptors().add(logging);
        // Ahora agrega el método .client y como parámetro el objeto httpClient
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://myapirest")
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient)
.build();

pero la idea es la que sugiere el colega, solo que cambia un poco el codigo de poner el loglevel, saludos!

edgar macas

unread,
Nov 18, 2015, 6:39:45 PM11/18/15
to desarrolladores-android
Gracias a todos por su ayuda lo logre solucionar :) 
 Estoy utilizando la version de retrofit 2 por lo que utilice:

HttpLoggingInterceptor logging = new HttpLoggingInterceptor();

logging
.setLevel(HttpLoggingInterceptor.Level.BODY); // NOTA CAMBIE HEADERS POR BODY PORQUE NO ME MOSTRABA EL ERROR

OkHttpClient httpClient = new OkHttpClient();

httpClient
.interceptors().add(logging);

con este codigo me arrojo lo siguiente: 
D/OkHttp: {"email":"ed...@gmail.com","latitud":-79.097676,"longitud":4.987654,"nombre":"android"}
D
/OkHttp: --> END POST (87-byte body)
D
/OkHttp: <-- HTTP/1.1 400 BAD REQUEST (612ms)
D
/OkHttp: Date: Wed, 18 Nov 2015 23:25:56 GMT
D
/OkHttp: Server: Apache/2.4.7 (Ubuntu)
D
/OkHttp: Allow: GET, POST, HEAD, OPTIONS
D
/OkHttp: X-Frame-Options: SAMEORIGIN
D
/OkHttp: Vary: Accept,Cookie
D
/OkHttp: Connection: close
D
/OkHttp: Transfer-Encoding: chunked
D
/OkHttp: Content-Type: application/json
D
/OkHttp: OkHttp-Selected-Protocol: http/1.1
D
/OkHttp: OkHttp-Sent-Millis: 1447890371797
D
/OkHttp: OkHttp-Received-Millis: 1447890372028
D
/OkHttp: {"correo":["This field is required."]}
D
/OkHttp: <-- END HTTP (38-byte body)

pues el error era por el campo email que estaba enviando y el apirest estaba esperando el campo correo, un error al momento de crear el modelo :)
un error de nombres pero que me estaba sacando canas verdes..
me sirvio su ayuda gracias. colegas

luiX_

unread,
Nov 19, 2015, 7:22:43 AM11/19/15
to desarrolladores-android

Sin ánimo de ofender ni crear polémicas, ya que te van ayudado y es posible que alguien más llegue aquí con el mismo problema, no estaría de más que dijeras cuál era el problema.

Un saludo!


--
Para participar es necesario que leas detenidamente las normas del grupo: http://goo.gl/8h8ez2
---
Has recibido este mensaje porque estás suscrito al grupo "desarrolladores-android" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a desarrolladores-a...@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a desarrollad...@googlegroups.com.
Visita este grupo en http://groups.google.com/group/desarrolladores-android.
Para ver esta conversación en el sitio web, visita https://groups.google.com/d/msgid/desarrolladores-android/776c3aaf-7c09-4ccf-b76b-605bbf080e34%40googlegroups.com.
Para acceder a más opciones, visita https://groups.google.com/d/optout.

Eduardo Martin Cabrera

unread,
Nov 19, 2015, 7:37:14 AM11/19/15
to desarrollad...@googlegroups.com
pues ya lo dijo, fue un error de nombres, si te fijas en lo publicado puede deducirse que se trata de que uso "email" en vez de "correo" para el nombre del parámetro, por eso siempre es bueno decidirse antes de comenzar cada proyecto y usar siempre un mismo idioma (de preferencia en inglés para nombrar las cosas, dado que eventualmente algún nombre podría no tener un buen equivalente en castellano, ser demasiado largo, etc), también "harcodear" menos en el código y en su lugar usar constantes ayuda a reducir estos errorcitos, saludos!
Reply all
Reply to author
Forward
This conversation is locked
You cannot reply and perform actions on locked conversations.
0 new messages