¿Cómo registrar el cuerpo de solicitud y respuesta con Retrofit-Android?

129

No puedo encontrar métodos relevantes en la API Retrofit para registrar cuerpos completos de solicitud / respuesta. Esperaba algo de ayuda en el Profiler (pero solo ofrece metadatos sobre la respuesta). Intenté configurar el nivel de registro en el generador, pero esto tampoco me ayuda:

RestAdapter adapter = (new RestAdapter.Builder()).
                setEndpoint(baseUrl).
                setRequestInterceptor(interceptor).
                setProfiler(profiler).
                setClient(client).
                setExecutors(MyApplication.getWebServiceThreadPool()).
                setLogLevel(LogLevel.FULL).
                setLog(new RestAdapter.Log() {
                    @Override
                    public void log(String msg) {
                        Log.i(TAG, msg);
                    }
                }).
                build();

EDITAR: este código está funcionando ahora. No sé por qué no estaba funcionando antes. Posiblemente porque estaba usando alguna versión anterior de retroadaptación.

Jaguar
fuente
¿Alguna vez resolviste esto? La documentación dice que FULLse supone que debe dar el cuerpo, pero no parece.
theblang
1
@mattblang: No sé qué estaba mal antes, pero este código está funcionando ahora.
Jaguar
Posible duplicado del registro con Retrofit 2
bryant1410
Probablemente la ejecución instantánea se estropeó un poco si no funcionó antes
deathangel908

Respuestas:

91

Solía setLogLevel(LogLevel.FULL).setLog(new AndroidLog("YOUR_LOG_TAG")), me ayudó.
ACTUALIZAR.
También puede intentar el uso de depuración retrofit.client.Responsecomo modelo de respuesta

Alex Dzeshko
fuente
2
AndroidLog, que clase es esa?
theblang
Viene con la biblioteca Retrofit.
Alex Dzeshko
2
Veo. Desafortunadamente, esto no te da el response body, aunque sí dice en el documento que LogLevel.FULL debería darte el response body.
theblang
Esto se puede ver con "YOUR_LOG_TAG" en Android Logcat en la pestaña detallada.
rajeesh
44
LogLevel.Full no existe en la
121

Retrofit 2.0 :

ACTUALIZACIÓN: @by Marcus Pöhls

Inicio de sesión en Retrofit 2

Retrofit 2 se basa completamente en OkHttp para cualquier operación de red. Dado que OkHttp es una dependencia entre pares de Retrofit 2, no necesitará agregar una dependencia adicional una vez que Retrofit 2 se lance como una versión estable.

OkHttp 2.6.0 se envía con un interceptor de registro como una dependencia interna y puede usarlo directamente para su cliente Retrofit. Retrofit 2.0.0-beta2 todavía usa OkHttp 2.5.0. Las versiones futuras aumentarán la dependencia de versiones OkHttp superiores. Es por eso que necesita importar manualmente el interceptor de registro. Agregue la siguiente línea a sus importaciones de gradle dentro de su archivo build.gradle para obtener la dependencia del interceptor de registro.

compile 'com.squareup.okhttp3:logging-interceptor:3.9.0'

También puede visitar la página de Square GitHub sobre este interceptor

Agregar registro a la actualización 2

Al desarrollar su aplicación y para fines de depuración, es bueno tener una función de registro integrada para mostrar información de solicitud y respuesta. Dado que el registro ya no está integrado por defecto en Retrofit 2, debemos agregar un interceptor de registro para OkHttp. Afortunadamente, OkHttp ya viene con este interceptor y solo necesita activarlo para su OkHttpClient.

HttpLoggingInterceptor logging = new HttpLoggingInterceptor();  
// set your desired log level
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();   
// add your other interceptors …
// add logging as last interceptor
httpClient.addInterceptor(logging);  // <-- this is the important line!
Retrofit retrofit = new Retrofit.Builder()  
        .baseUrl(API_BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .client(httpClient.build())
        .build();

Recomendamos agregar el registro como el último interceptor, ya que esto también registrará la información que agregó con interceptores anteriores a su solicitud.

Niveles de registro

Registrar demasiada información hará explotar su monitor Android, es por eso que el interceptor de registro de OkHttp tiene cuatro niveles de registro: NINGUNO, BÁSICO, CABEZALES, CUERPO. Le guiaremos a través de cada uno de los niveles de registro y describiremos su salida.

Para obtener más información, visite: Retrofit 2 - Registro de solicitudes y respuestas

ANTIGUA RESPUESTA:

ya no es necesario iniciar sesión en Retrofit 2. El equipo de desarrollo eliminó la función de registro. Para ser honesto, la función de registro no era tan confiable de todos modos. Jake Wharton declaró explícitamente que los mensajes u objetos registrados son los valores asumidos y que no se puede probar que sean ciertos. La solicitud real que llega al servidor puede tener un cuerpo de solicitud cambiado u otra cosa.

Aunque no existe un registro integrado de forma predeterminada, puede aprovechar cualquier registrador Java y usarlo dentro de un interceptor OkHttp personalizado.

Para obtener más información sobre Retrofit 2, consulte: Retrofit : cómo comenzar y crear un cliente Android

Dhaval Jivani
fuente
1
También hay una publicación específica para iniciar sesión en Retrofit 2.0: futurestud.io/blog/retrofit-2-log-requests-and-responses
peitek
Gran manera de hacer todo más complicado de lo que debería ser. Me recuerda el registro de Jersey 1 vs Jersey 2. Más código
repetitivo
Agregar interceptores de esta manera ahora dará como resultado una excepción de operación no admitida en OkHttp v3. La nueva forma es: OkHttpClient.Builder (). AddInterceptor (logging) .build () github.com/square/okhttp/issues/2219
Amagi82
@JawadLeWywadi sí, usando este código puede imprimir el cuerpo
Dhaval Jivani
Para Retrofit 2, esto es mucho más fácil.
Gary99
31

Actualización para Retrofit 2.0.0-beta3

Ahora tienes que usar okhttp3 con el constructor. Además, el viejo interceptor no funcionará. Esta respuesta está diseñada para Android.

Aquí hay una copia rápida de pegar para usted con las nuevas cosas.

1. Modifique su archivo gradle a

  compile 'com.squareup.retrofit2:retrofit:2.0.0-beta3'
  compile "com.squareup.retrofit2:converter-gson:2.0.0-beta3"
  compile "com.squareup.retrofit2:adapter-rxjava:2.0.0-beta3"
  compile 'com.squareup.okhttp3:logging-interceptor:3.0.1'

2. Verifique este código de muestra:

con las nuevas importaciones. Puede eliminar Rx si no lo usa, también elimine lo que no usa.

import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.GsonConverterFactory;
import retrofit2.Retrofit;
import retrofit2.RxJavaCallAdapterFactory;
import retrofit2.http.GET;
import retrofit2.http.Query;
import rx.Observable;

public interface APIService {

  String ENDPOINT = "http://api.openweathermap.org";
  String API_KEY = "2de143494c0b2xxxx0e0";

  @GET("/data/2.5/weather?appid=" + API_KEY) Observable<WeatherPojo> getWeatherForLatLon(@Query("lat") double lat, @Query("lng") double lng, @Query("units") String units);


  class Factory {

    public static APIService create(Context context) {

      OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
      builder.readTimeout(10, TimeUnit.SECONDS);
      builder.connectTimeout(5, TimeUnit.SECONDS);

      if (BuildConfig.DEBUG) {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
        builder.addInterceptor(interceptor);
      }

      //Extra Headers

      //builder.addNetworkInterceptor().add(chain -> {
      //  Request request = chain.request().newBuilder().addHeader("Authorization", authToken).build();
      //  return chain.proceed(request);
      //});

      builder.addInterceptor(new UnauthorisedInterceptor(context));
      OkHttpClient client = builder.build();

      Retrofit retrofit =
          new Retrofit.Builder().baseUrl(APIService.ENDPOINT).client(client).addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJavaCallAdapterFactory.create()).build();

      return retrofit.create(APIService.class);
    }
  }
}

Prima

Sé que es offtopic pero me parece genial.

En caso de que haya un código de error http no autorizado , aquí hay un interceptor. Yo uso eventbus para transmitir el evento.

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import com.androidadvance.ultimateandroidtemplaterx.BaseApplication;
import com.androidadvance.ultimateandroidtemplaterx.events.AuthenticationErrorEvent;

import de.greenrobot.event.EventBus;
import java.io.IOException;
import javax.inject.Inject;
import okhttp3.Interceptor;
import okhttp3.Response;

public class UnauthorisedInterceptor implements Interceptor {

  @Inject EventBus eventBus;

  public UnauthorisedInterceptor(Context context) {
    BaseApplication.get(context).getApplicationComponent().inject(this);
  }

  @Override public Response intercept(Chain chain) throws IOException {
    Response response = chain.proceed(chain.request());
    if (response.code() == 401) {
      new Handler(Looper.getMainLooper()).post(() -> eventBus.post(new AuthenticationErrorEvent()));
    }
    return response;
  }
}

toma de código de https://github.com/AndreiD/UltimateAndroidTemplateRx (mi proyecto).

OWADVL
fuente
9

No parece haber una forma de hacer cuerpo básico +, pero puede usar COMPLETO y filtrar los encabezados que no desea.

RestAdapter adapter = new RestAdapter.Builder()
                          .setEndpoint(syncServer)
                          .setErrorHandler(err)
                          .setConverter(new GsonConverter(gson))
                          .setLogLevel(logLevel)
                          .setLog(new RestAdapter.Log() {
                              @Override
                              public void log(String msg) {
                                  String[] blacklist = {"Access-Control", "Cache-Control", "Connection", "Content-Type", "Keep-Alive", "Pragma", "Server", "Vary", "X-Powered-By"};
                                  for (String bString : blacklist) {
                                      if (msg.startsWith(bString)) {
                                          return;
                                      }
                                  }
                                  Log.d("Retrofit", msg);
                              }
                          }).build();

Parece que al anular el registro, el cuerpo tiene el prefijo de una etiqueta similar a

[ 02-25 10:42:30.317 25645:26335 D/Retrofit ]

Por lo tanto, debería ser fácil registrar el cuerpo básico + ajustando el filtro personalizado. Estoy usando una lista negra, pero también podría usarse una lista blanca dependiendo de sus necesidades.

Xeridea
fuente
4

El siguiente código funciona tanto con el encabezado como sin el encabezado para imprimir la solicitud y la respuesta del registro. Nota: Solo comente la línea .addHeader () si no está usando el encabezado.

HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(interceptor)
                //.addInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
                .addNetworkInterceptor(new Interceptor() {

                    @Override

                    public okhttp3.Response intercept(Chain chain) throws IOException {
                        Request request = chain.request().newBuilder()
                                // .addHeader(Constant.Header, authToken)
                                   .build();
                        return chain.proceed(request);
                    }
                }).build();

        final Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Constant.baseUrl)
                .client(client) // This line is important
                .addConverterFactory(GsonConverterFactory.create())
                .build();
Mukesh Parmar
fuente
3

Espero que este código te ayude a iniciar sesión.
solo necesita agregar un interceptor en su Build.Gradlemarca RetrofitClient.

Primer paso

Agregue esta línea a su build.gradle

 implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1' 

Segundo paso

Haga su cliente de modificación


   public class RetrofitClient {

    private Retrofit retrofit;
    private static OkHttpClient.Builder httpClient =
            new OkHttpClient.Builder();
    private static RetrofitClient instance = null;
    private static ApiServices service = null;
    private static HttpLoggingInterceptor logging =
            new HttpLoggingInterceptor();

    private RetrofitClient(final Context context) {
        httpClient.interceptors().add(new Interceptor() {
            @Override
            public okhttp3.Response intercept(Interceptor.Chain chain) throws IOException {
                Request originalRequest = chain.request();
                Request.Builder builder = originalRequest.newBuilder().
                        method(originalRequest.method(), originalRequest.body());
                okhttp3.Response response = chain.proceed(builder.build());
                /*
                Do what you want
                 */
                return response;
            }
        });

        if (BuildConfig.DEBUG) {
            logging.setLevel(HttpLoggingInterceptor.Level.BODY);
            // add logging as last interceptor
            httpClient.addInterceptor(logging);
        }

        retrofit = new Retrofit.Builder().client(httpClient.build()).
                baseUrl(Constants.BASE_URL).
                addConverterFactory(GsonConverterFactory.create()).build();
        service = retrofit.create(ApiServices.class);
    }


    public static RetrofitClient getInstance(Context context) {
        if (instance == null) {
            instance = new RetrofitClient(context);
        }
        return instance;
    }

    public ApiServices getApiService() {
        return service;
    }
}

Vocación

RetrofitClient.getInstance(context).getApiService().yourRequestCall(); 
Talha Bilal
fuente
2

Si está utilizando Retrofit2 y okhttp3, debe saber que Interceptor funciona en cola. Agregue loggingInterceptor al final, después de sus otros interceptores:

HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
        if (BuildConfig.DEBUG)
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);

 new OkHttpClient.Builder()
                .connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
                .addInterceptor(new CatalogInterceptor(context))
                .addInterceptor(new OAuthInterceptor(context))
                .authenticator(new BearerTokenAuthenticator(context))
                .addInterceptor(loggingInterceptor)//at the end
                .build();
NickUnuchek
fuente