WebApiに対するRequestとResponseをログに出したい。WebApiを叩く処理でログ出力するのが面倒なので、SpringのRestTemplateにログを出力するInterceptorを足して対応してみた。
試してないですが logging: level: org.springframework.web.client.RestTemplate: DEBUG
でDebugにするとRequestとResponseがログに出せたりするらしい。ただ、ログに出したいだけならこっちのほうが簡単かも。
Java8でSpring boot 1.5.6を使ってます。
RestTemplateの設定
ログ出力をする様にClientHttpRequestInterceptorを実装して、RestTemplateに設定します。ログ出力はお好みで。
clientHttpRequestExecution.execute(httpRequest, bytes)
の結果が1度しか読めないのでWrapperを定義してます。
@Configuration public class WebApiClientConfig { @Bean public RestTemplate restTemplate() { return new RestTemplateBuilder().additionalInterceptors( Collections.singletonList(new LoggingClientHttpRequestInterceptor())).build(); }
@Slf4j private static class LoggingClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { @Override public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] bytes, ClientHttpRequestExecution clientHttpRequestExecution) throws IOException { log.info("Request: URI={}, Headers={}, Body={}", httpRequest.getURI(), httpRequest.getHeaders(), new String(bytes)); ClientHttpResponse response = new BufferingClientHttpResponseWrapper(clientHttpRequestExecution.execute(httpRequest, bytes)); if (!response.getStatusCode().is2xxSuccessful()) { throw new RuntimeException("Api failed. Response: Status=" + response.getStatusCode() + ", Body=" + StreamUtils.copyToString(response.getBody(), Charset.defaultCharset())); } log.info("Response: Body={}", StreamUtils.copyToString(response.getBody(), Charset.defaultCharset())); return response; } }
private static class BufferingClientHttpResponseWrapper implements ClientHttpResponse { private final ClientHttpResponse response; private byte[] body;
public BufferingClientHttpResponseWrapper(ClientHttpResponse response) { this.response = response; }
public HttpStatus getStatusCode() throws IOException { return this.response.getStatusCode(); }
public int getRawStatusCode() throws IOException { return this.response.getRawStatusCode(); }
public String getStatusText() throws IOException { return this.response.getStatusText(); }
public HttpHeaders getHeaders() { return this.response.getHeaders(); }
public InputStream getBody() throws IOException { if (this.body == null) { this.body = StreamUtils.copyToByteArray(this.response.getBody()); } return new ByteArrayInputStream(this.body); }
public void close() { this.response.close(); } } }
|
使ってみる
ログが出るか確認するだけの適当なクラスとメソッドを作る。
@Component public class GithubClient { @Autowired private RestTemplate restTemplate;
public String getHome() { return restTemplate.getForObject("https://github.com/ishiis", String.class); } }
|
テストする。
@RunWith(SpringRunner.class) @SpringBootTest public class GithubClientTest { @Autowired private GithubClient githubClient;
@Test public void testGetHome() { Assert.assertNotNull(githubClient.getHome()); } }
|
テストを実行すると、
といった感じのログが出るはず。
おわり。
参考
- https://stackoverflow.com/questions/7952154/spring-resttemplate-how-to-enable-full-debugging-logging-of-requests-responses