apache httpclient 요청 디버깅
이전 포스팅에서 Apache httpclient를 이용하여 http요청을 보내는 방법에 대한 포스팅을 올린적이 있습니다. 사실 http는 평이한 구조의 프로토콜 이므로 요청 내용을 살펴보는 것만으로도 디버깅이 수월하게 할 수 있습니다. 이러한 요청 내용을 살펴보는 방법에는 여러가지 방법이 있을수 있겠지만 본 포스팅에서는 httpclient에서 제공하는 로깅기능을 이용하여 직접 출력하는 방법과 프록시(proxy)를 이용하여 서버와 클라이언트 중간에서 요청을 중개하면서 확인하는 방법에 대해서 소개하도록 하겠습니다.
Proxy를 통한 httpclient 요청 디버깅
try { RequestConfig.Builder requestBuilder = RequestConfig.custom(); requestBuilder.setProxy(new HttpHost("127.0.0.1", 8888, "http")); HttpClientBuilder builder = HttpClientBuilder.create(); builder.setDefaultRequestConfig(requestBuilder.build()); HttpClient client = builder.build(); HttpGet httpGet = new HttpGet(new URI("요청을 보낼 URL")); HttpResponse response = client.execute(httpGet); System.out.println(EntityUtils.toString(response.getEntity())); } catch (URISyntaxException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
기본적인 http 요청 코드에 프록시를 설정하는 메소드를 호출해서 프록시호스트를 전달해 주는 것으로서 디버깅을 할 수 있습니다. 위의 코드는 잘 알려진 http 디버깅 툴인 fiddler의 기본 설정인 8888번 포트에 프록시 설정을 하는 코드 입니다. 위의 코드를 실행하게 되면 아래와 같이 fiddler에서 요청을 확인할 수 있습니다. 요청하는 소스코드에 단 한줄만 추가하는 것만으로 쉽게 요청 내용을 확인할 수 있으므로 매우 편리하게 사용할 수 있습니다.
Log4J의 로거를 이용한 httpclient 요청 디버깅
log4j.rootLogger=INFO, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%c] %m%n log4j.logger.org.apache.http=DEBUG log4j.logger.org.apache.http.wire=ERROR
위의 log4j 설정은 Apache httpclient 4.3 Logging Guide에서 발췌한 내용으로 디버깅 시에 가장 추천하는 형태의 로거 설정입니다. 위의 설정후 출력되는 로그를 확인하면 아래와 같습니다.
DEBUG [org.apache.http.client.protocol.RequestAddCookies] CookieSpec selected: best-match DEBUG [org.apache.http.client.protocol.RequestAuthCache] Auth cache not set in the context DEBUG [org.apache.http.impl.conn.PoolingHttpClientConnectionManager] Connection request: [route: {}->####접속URL####][total kept alive: 0; route allocated: 0 of 2; total allocated: 0 of 20] DEBUG [org.apache.http.impl.conn.PoolingHttpClientConnectionManager] Connection leased: [id: 0][route: {}->####접속URL####][total kept alive: 0; route allocated: 1 of 2; total allocated: 1 of 20] DEBUG [org.apache.http.impl.execchain.MainClientExec] Opening connection {}->####접속URL#### DEBUG [org.apache.http.conn.HttpClientConnectionManager] Connecting to ####접속URL####/####접속IP#### DEBUG [org.apache.http.impl.execchain.MainClientExec] Executing request GET / HTTP/1.1 DEBUG [org.apache.http.impl.execchain.MainClientExec] Target auth state: UNCHALLENGED DEBUG [org.apache.http.impl.execchain.MainClientExec] Proxy auth state: UNCHALLENGED DEBUG [org.apache.http.headers] http-outgoing-0 >> GET / HTTP/1.1 DEBUG [org.apache.http.headers] http-outgoing-0 >> Host: ####접속호스트명#### DEBUG [org.apache.http.headers] http-outgoing-0 >> Connection: Keep-Alive DEBUG [org.apache.http.headers] http-outgoing-0 >> User-Agent: Apache-HttpClient/4.3.2 (java 1.5) DEBUG [org.apache.http.headers] http-outgoing-0 >> Accept-Encoding: gzip,deflate DEBUG [org.apache.http.headers] http-outgoing-0 << HTTP/1.1 200 OK DEBUG [org.apache.http.headers] http-outgoing-0 << Server: nginx DEBUG [org.apache.http.headers] http-outgoing-0 << Date: Wed, 26 Nov 2014 14:41:31 GMT DEBUG [org.apache.http.headers] http-outgoing-0 << Content-Type: text/html; charset=UTF-8 DEBUG [org.apache.http.headers] http-outgoing-0 << Transfer-Encoding: chunked DEBUG [org.apache.http.headers] http-outgoing-0 << Connection: close DEBUG [org.apache.http.headers] http-outgoing-0 << Cache-Control: no-cache, no-store, must-revalidate DEBUG [org.apache.http.headers] http-outgoing-0 << Pragma: no-cache DEBUG [org.apache.http.headers] http-outgoing-0 << P3P: CP="CAO DSP CURa ADMa TAIa PSAa OUR LAW STP PHY ONL UNI PUR FIN COM NAV INT DEM STA PRE" DEBUG [org.apache.http.headers] http-outgoing-0 << X-Frame-Options: SAMEORIGIN DEBUG [org.apache.http.headers] http-outgoing-0 << Content-Encoding: gzip
아시다시피 Log4J의 로거는 카테고리구조로 되어있으며 위의 설정은 org.apache.http 카테고리는 debug모드로 하위의 org.apache.http.wire는 error레벨로 지정했습니다. 위의 예에서 org.apache.http.wire의 로거 설정을 제거하면 전체가 debug모드가 되면서 전체 컨텍스트가 출력되게 됩니다만 알아보기 힘든 문자들이 출력되므로 디버깅에 그리 좋은 형태는 아닙니다. 따라서 일반적인 경우라는 위의 추천 로거 설정을 사용하면 될 듯 합니다.
※위의 로그에서 []사이의 카테고리를 참조하시면 필요한 로그 정보만 출력하도록 로거를 구성할 수 있습니다. 또한 로거에 대한 자세한 내용은 Apache HttpComponents 홈페이지에서 확인할 수 있습니다.
참조 : https://hc.apache.org/httpcomponents-client-4.3.x/logging.html