diff --git a/core/src/main/java/feign/Logger.java b/core/src/main/java/feign/Logger.java index a40362093..cb38ed8e1 100644 --- a/core/src/main/java/feign/Logger.java +++ b/core/src/main/java/feign/Logger.java @@ -72,7 +72,7 @@ protected boolean shouldLogResponseHeader(String header) { protected void logRequest(String configKey, Level logLevel, Request request) { String protocolVersion = resolveProtocolVersion(request.protocolVersion()); log(configKey, "---> %s %s %s", request.httpMethod().name(), request.url(), protocolVersion); - if (logLevel.ordinal() >= Level.HEADERS.ordinal()) { + if (logLevel.atLeast(Level.HEADERS)) { for (String field : request.headers().keySet()) { if (shouldLogRequestHeader(field)) { @@ -85,7 +85,7 @@ protected void logRequest(String configKey, Level logLevel, Request request) { int bodyLength = 0; if (request.body() != null) { bodyLength = request.length(); - if (logLevel.ordinal() >= Level.FULL.ordinal()) { + if (logLevel.atLeast(Level.FULL)) { String bodyText = request.charset() != null ? new String(request.body(), request.charset()) : null; log(configKey, ""); // CRLF @@ -104,32 +104,23 @@ protected Response logAndRebufferResponse( String configKey, Level logLevel, Response response, long elapsedTime) throws IOException { String protocolVersion = resolveProtocolVersion(response.protocolVersion()); String reason = - response.reason() != null && logLevel.compareTo(Level.NONE) > 0 - ? " " + response.reason() - : ""; + response.reason() != null && logLevel.atLeast(Level.BASIC) ? " " + response.reason() : ""; int status = response.status(); log(configKey, "<--- %s %s%s (%sms)", protocolVersion, status, reason, elapsedTime); - if (logLevel.ordinal() >= Level.HEADERS.ordinal()) { + if (logLevel.atLeast(Level.HEADERS)) { - for (String field : response.headers().keySet()) { - if (shouldLogResponseHeader(field)) { - for (String value : valuesOrEmpty(response.headers(), field)) { - log(configKey, "%s: %s", field, value); - } - } - } + logResponseHeaders(configKey, response); int bodyLength = 0; if (response.body() != null && !(status == 204 || status == 205)) { // HTTP 204 No Content "...response MUST NOT include a message-body" // HTTP 205 Reset Content "...response MUST NOT include an entity" - if (logLevel.ordinal() >= Level.FULL.ordinal()) { + if (logLevel.atLeast(Level.FULL)) { log(configKey, ""); // CRLF } - byte[] bodyData = Util.toByteArray(response.body().asInputStream()); - ensureClosed(response.body()); + byte[] bodyData = rebufferBody(response); bodyLength = bodyData.length; - if (logLevel.ordinal() >= Level.FULL.ordinal() && bodyLength > 0) { + if (logLevel.atLeast(Level.FULL) && bodyLength > 0) { log(configKey, "%s", decodeOrDefault(bodyData, UTF_8, "Binary data")); } log(configKey, "<--- END HTTP (%s-byte body)", bodyLength); @@ -141,6 +132,22 @@ protected Response logAndRebufferResponse( return response; } + private void logResponseHeaders(String configKey, Response response) { + for (String field : response.headers().keySet()) { + if (shouldLogResponseHeader(field)) { + for (String value : valuesOrEmpty(response.headers(), field)) { + log(configKey, "%s: %s", field, value); + } + } + } + } + + private byte[] rebufferBody(Response response) throws IOException { + byte[] bodyData = Util.toByteArray(response.body().asInputStream()); + ensureClosed(response.body()); + return bodyData; + } + protected IOException logIOException( String configKey, Level logLevel, IOException ioe, long elapsedTime) { log( @@ -149,7 +156,7 @@ protected IOException logIOException( ioe.getClass().getSimpleName(), ioe.getMessage(), elapsedTime); - if (logLevel.ordinal() >= Level.FULL.ordinal()) { + if (logLevel.atLeast(Level.FULL)) { StringWriter sw = new StringWriter(); ioe.printStackTrace(new PrintWriter(sw)); log(configKey, "%s", sw.toString()); @@ -174,7 +181,12 @@ public enum Level { /** Log the basic information along with request and response headers. */ HEADERS, /** Log the headers, body, and metadata for both requests and responses. */ - FULL + FULL; + + /** Returns {@code true} if this level is at least as verbose as {@code other}. */ + public boolean atLeast(Level other) { + return ordinal() >= other.ordinal(); + } } /** Logs to System.err. */ diff --git a/core/src/main/java/feign/Response.java b/core/src/main/java/feign/Response.java index c1b175ced..b09a3fd52 100644 --- a/core/src/main/java/feign/Response.java +++ b/core/src/main/java/feign/Response.java @@ -55,11 +55,11 @@ public static Builder builder() { public static final class Builder { private static final ProtocolVersion DEFAULT_PROTOCOL_VERSION = ProtocolVersion.HTTP_1_1; - int status; - String reason; - Map> headers; - Body body; - Request request; + private int status; + private String reason; + private Map> headers; + private Body body; + private Request request; private RequestTemplate requestTemplate; private ProtocolVersion protocolVersion = DEFAULT_PROTOCOL_VERSION; diff --git a/core/src/test/java/feign/LoggerMethodsTest.java b/core/src/test/java/feign/LoggerMethodsTest.java index bee76be63..01f08d51e 100644 --- a/core/src/test/java/feign/LoggerMethodsTest.java +++ b/core/src/test/java/feign/LoggerMethodsTest.java @@ -54,4 +54,19 @@ void responseIsClosedAfterRebuffer() throws IOException { verify(spyBody).close(); assertThat(rebufferedResponse.body()).isNotSameAs(spyBody); } + + @Test + void atLeastReturnsTrueForEqualLevel() { + assertThat(Level.BASIC.atLeast(Level.BASIC)).isTrue(); + } + + @Test + void atLeastReturnsTrueWhenMoreVerbose() { + assertThat(Level.FULL.atLeast(Level.HEADERS)).isTrue(); + } + + @Test + void atLeastReturnsFalseWhenLessVerbose() { + assertThat(Level.NONE.atLeast(Level.FULL)).isFalse(); + } }