OkHttp how to log request body

前端 未结 5 1690
深忆病人
深忆病人 2020-12-13 11:51

I\'m using an interceptor, and I would like to log the body of a request I\'m making but I can\'t see any way of doing this.

Is it possible ?

public         


        
相关标签:
5条回答
  • 2020-12-13 12:26

    Nikola's answer did not work for me. My guess is the implementation of ByteString#toString() changed. This solution worked for me:

    private static String bodyToString(final 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";
        }
    }
    

    From the documentation of readUtf8():

    Removes all bytes from this, decodes them as UTF-8, and returns the string.

    which should be what you want.

    0 讨论(0)
  • 2020-12-13 12:31

    I tried to comment on the correct answer from @msung, but my reputation isn't high enough.

    Here's modification I did to print RequestBody before making it a full request. It works like a charm. Thanks

    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";
            }
    }
    
    0 讨论(0)
  • 2020-12-13 12:33

    With a current version of OkHttp, you can use the HTTP Logging Interceptor and set the level to BODY

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

    With this you cannot granularily configure the output for different HTTP methods, but it also works for other methods that might have a body.

    Here an example showing the output of a PATCH request (minimally redacted):

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

    As you can see, this also prints out the headers and as the documentation states, you should really take care:

    The logs generated by this interceptor when using the HEADERS or BODY levels have the potential to leak sensitive information such as "Authorization" or "Cookie" headers and the contents of request and response bodies. This data should only be logged in a controlled way or in a non-production environment.

    You can redact headers that may contain sensitive information by calling redactHeader().

    logging.redactHeader("Authorization");
    logging.redactHeader("Cookie");
    
    0 讨论(0)
  • 2020-12-13 12:37

    EDIT

    Because I see there is still some people interested by this post, here is the final version (until next improvement) of my log interceptor. I hope it will save some of you guys's time.

    Please note that this code is using OkHttp 2.2.0 (and Retrofit 1.9.0)

    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;
    }
    }
    
    0 讨论(0)
  • 2020-12-13 12:40

    Version that handles requests with or without a body:

    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 "";
    }
    
    0 讨论(0)
提交回复
热议问题