android OkHttp, wie Anforderungshauptteil protokolliert wird



okhttp release notes (4)

Ich verwende einen Abfangjäger und möchte den Hauptteil einer Anfrage, die ich stelle, protokollieren, sehe aber keine Möglichkeit, dies zu tun.

Ist es möglich ?

public class LoggingInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();

        long t1 = System.nanoTime();
        Response response = chain.proceed(request);
        long t2 = System.nanoTime();

        double time = (t2 - t1) / 1e6d;

        if (request.method().equals("GET")) {
            Logs.info(String.format("GET " + F_REQUEST_WITHOUT_BODY + F_RESPONSE_WITH_BODY, request.url(), time, request.headers(), response.code(), response.headers(), response.body().charStream()));
        } else if (request.method().equals("POST")) {
            Logs.info(String.format("POST " + F_REQUEST_WITH_BODY + F_RESPONSE_WITH_BODY, request.url(), time, request.headers(), request.body(), response.code(), response.headers(), response.body().charStream()));
        } else if (request.method().equals("PUT")) {
            Logs.info(String.format("PUT " + F_REQUEST_WITH_BODY + F_RESPONSE_WITH_BODY, request.url(), time, request.headers(), request.body().toString(), response.code(), response.headers(), response.body().charStream()));
        } else if (request.method().equals("DELETE")) {
            Logs.info(String.format("DELETE " + F_REQUEST_WITHOUT_BODY + F_RESPONSE_WITHOUT_BODY, request.url(), time, request.headers(), response.code(), response.headers()));
        }

        return response;
    }
}

und das Ergebnis:

POST  [some url] in 88,7ms
    ZoneName: touraine
    Source: Android
    body: retrofit.client.[email protected] <-request.body().toString() gives me this, but I would like the content string
    Response: 500
    Date: Tue, 24 Feb 2015 10:14:22 GMT
    body: [some content] 

Answer #1

Version, die Anfragen mit oder ohne Body bearbeitet:

private String stringifyRequestBody(Request request) {
  if (request.body() != null) {
      try {
          final Request copy = request.newBuilder().build();
          final Buffer buffer = new Buffer();
          copy.body().writeTo(buffer);
          return buffer.readUtf8();
      } catch (final IOException e) {
          Log.w(TAG, "Failed to stringify request body: " + e.getMessage());
      }
  }
  return "";
}

Answer #2

BEARBEITEN

Da ich sehe, dass noch einige Leute an diesem Beitrag interessiert sind, ist hier die endgültige Version (bis zur nächsten Verbesserung) meines Log Interceptors. Ich hoffe, es spart einigen von euch Zeit.

Bitte beachten Sie, dass dieser Code OkHttp 2.2.0 (und Retrofit 1.9.0 ) verwendet.

import com.squareup.okhttp.*;
import okio.Buffer;
import java.io.IOException;

public class LoggingInterceptor implements Interceptor {

private static final String F_BREAK = " %n";
private static final String F_URL = " %s";
private static final String F_TIME = " in %.1fms";
private static final String F_HEADERS = "%s";
private static final String F_RESPONSE = F_BREAK + "Response: %d";
private static final String F_BODY = "body: %s";

private static final String F_BREAKER = F_BREAK + "-------------------------------------------" + F_BREAK;
private static final String F_REQUEST_WITHOUT_BODY = F_URL + F_TIME + F_BREAK + F_HEADERS;
private static final String F_RESPONSE_WITHOUT_BODY = F_RESPONSE + F_BREAK + F_HEADERS + F_BREAKER;
private static final String F_REQUEST_WITH_BODY = F_URL + F_TIME + F_BREAK + F_HEADERS + F_BODY + F_BREAK;
private static final String F_RESPONSE_WITH_BODY = F_RESPONSE + F_BREAK + F_HEADERS + F_BODY + F_BREAK + F_BREAKER;

@Override
public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();

    long t1 = System.nanoTime();
    Response response = chain.proceed(request);
    long t2 = System.nanoTime();

    MediaType contentType = null;
    String bodyString = null;
    if (response.body() != null) {
        contentType = response.body().contentType();
        bodyString = response.body().string();
    }

    double time = (t2 - t1) / 1e6d;

    if (request.method().equals("GET")) {
        System.out.println(String.format("GET " + F_REQUEST_WITHOUT_BODY + F_RESPONSE_WITH_BODY, request.url(), time, request.headers(), response.code(), response.headers(), stringifyResponseBody(bodyString)));
    } else if (request.method().equals("POST")) {
        System.out.println(String.format("POST " + F_REQUEST_WITH_BODY + F_RESPONSE_WITH_BODY, request.url(), time, request.headers(), stringifyRequestBody(request), response.code(), response.headers(), stringifyResponseBody(bodyString)));
    } else if (request.method().equals("PUT")) {
        System.out.println(String.format("PUT " + F_REQUEST_WITH_BODY + F_RESPONSE_WITH_BODY, request.url(), time, request.headers(), request.body().toString(), response.code(), response.headers(), stringifyResponseBody(bodyString)));
    } else if (request.method().equals("DELETE")) {
        System.out.println(String.format("DELETE " + F_REQUEST_WITHOUT_BODY + F_RESPONSE_WITHOUT_BODY, request.url(), time, request.headers(), response.code(), response.headers()));
    }

    if (response.body() != null) {
        ResponseBody body = ResponseBody.create(contentType, bodyString);
        return response.newBuilder().body(body).build();
    } else {
        return response;
    }
}


private static String stringifyRequestBody(Request request) {
    try {
        final Request copy = request.newBuilder().build();
        final Buffer buffer = new Buffer();
        copy.body().writeTo(buffer);
        return buffer.readUtf8();
    } catch (final IOException e) {
        return "did not work";
    }
}

public String stringifyResponseBody(String responseBody) {
    return responseBody;
}
}

Answer #3

Mit einer aktuellen Version von OkHttp können Sie den HTTP Logging Interceptor verwenden und die Stufe auf BODY

HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(Level.BODY);

Mit dieser Option können Sie die Ausgabe nicht detailliert für verschiedene HTTP-Methoden konfigurieren, sondern auch für andere Methoden, die möglicherweise einen Body haben.

Hier ein Beispiel für die Ausgabe einer PATCH Anfrage (minimal überarbeitet):

--> PATCH https://hostname/api/something/123456 HTTP/1.1
Content-Type: application/json-patch+json; charset=utf-8
Content-Length: 49
Authorization: Basic YWRtaW46c2VjcmV0Cg==
Accept: application/json

[ { "op": "add", "path": "/path", "value": true }]
--> END PATCH (xx-byte body)

Wie Sie sehen, werden hiermit auch die Überschriften ausgedruckt, und wie in der Dokumentation angegeben, sollten Sie Folgendes beachten:

In den von diesem Interceptor bei Verwendung der HEADERS oder BODY Ebenen generierten Protokollen können vertrauliche Informationen wie z. B. "Authorization" - oder "Cookie" -Header und der Inhalt von Anfrage- und Antwortkörpern verloren gehen. Diese Daten sollten nur kontrolliert oder in einer nicht produktiven Umgebung protokolliert werden.

Sie können Header, die vertrauliche Informationen enthalten können, durch Aufrufen von redactHeader() .

logging.redactHeader("Authorization");
logging.redactHeader("Cookie");

Answer #4

Ich habe versucht, die richtige Antwort von @msung zu kommentieren, aber mein Ruf ist nicht hoch genug.

Hier ist die Änderung, die ich vorgenommen habe, um RequestBody zu drucken, bevor eine vollständige Anforderung erstellt wurde. Es wirkt wie ein Zauber. Vielen Dank

private static String bodyToString(final RequestBody request){
        try {
            final RequestBody copy = request;
            final Buffer buffer = new Buffer();
            copy.writeTo(buffer);
            return buffer.readUtf8();
        } 
        catch (final IOException e) {
            return "did not work";
        }
}




okhttp