diff --git a/src/main/java/cokr/xit/foundation/web/WebClient.java b/src/main/java/cokr/xit/foundation/web/WebClient.java index 236fc7c..71bd3ba 100644 --- a/src/main/java/cokr/xit/foundation/web/WebClient.java +++ b/src/main/java/cokr/xit/foundation/web/WebClient.java @@ -4,6 +4,7 @@ import java.io.FileOutputStream; import java.io.InputStream; import java.math.BigInteger; import java.net.Authenticator; +import java.net.CookieHandler; import java.net.ProxySelector; import java.net.URI; import java.net.URLEncoder; @@ -83,12 +84,21 @@ import cokr.xit.foundation.data.JSON; * @author mjkhan */ public class WebClient { + /**http 통신의 로그를 출력하도록 설정한다. + */ + public static void debug() { + System.setProperty("jdk.httpclient.HttpClient.log", "errors,requests,headers,frames[:control:data:window:all],content,ssl,trace,channel,all"); + } + private HttpClient.Version version = HttpClient.Version.HTTP_2; private Duration timeout = Duration.ofSeconds(30); private Authenticator authenticator; private SSLContext sslContext; private ProxySelector proxy; + private Charset charset; + private CookieHandler cookieHandler; + private HttpClient.Redirect followRedirects = HttpClient.Redirect.NORMAL; /**http 프로토콜의 버젼을 설정한다. 디폴트는 HTTP/2 @@ -136,6 +146,24 @@ public class WebClient { return this; } + public Charset charset() { + return Assert.ifEmpty(charset, StandardCharsets.UTF_8); + } + + /**문자셋을 설정한다. 디폴트는 UTF-8. + * @param charset 요청의 문자셋 + * @return 현재 WebClient + */ + public WebClient charset(String charset) { + this.charset = Charset.forName(charset); + return this; + } + + public WebClient cookieHandler(CookieHandler cookieHandler) { + this.cookieHandler = cookieHandler; + return this; + } + /**서버의 응답이 redirect일 경우 대응 방법을 설정한다. 디폴트는 HttpClient.Redirect.NORMAL. * @param redirect redirect 응답에 대한 대응 방법 * @return 현재 WebClient @@ -145,20 +173,28 @@ public class WebClient { return this; } + private HttpClient client; + private HttpClient client() { - HttpClient.Builder builder = HttpClient.newBuilder() - .version(version) - .connectTimeout(timeout) - .followRedirects(followRedirects); - - if (authenticator != null) - builder.authenticator(authenticator); - if (sslContext != null) - builder.sslContext(sslContext); - if (proxy != null) - builder.proxy(proxy); - - return builder.build(); + if (client == null) { + HttpClient.Builder builder = HttpClient.newBuilder() + .version(version) + .connectTimeout(timeout) + .followRedirects(followRedirects); + + if (authenticator != null) + builder.authenticator(authenticator); + if (sslContext != null) + builder.sslContext(sslContext); + if (proxy != null) + builder.proxy(proxy); + + if (cookieHandler != null) + builder.cookieHandler(cookieHandler); + + client = builder.build(); + } + return client; } /**"GET" 방식의 요청을 전송한다. @@ -169,6 +205,7 @@ public class WebClient { @SuppressWarnings("unchecked") public HttpResponse get(Consumer configurer) { Request req = new Request(); + req.charset = charset(); configurer.accept(req); HttpRequest hreq = req.get(); @@ -190,12 +227,12 @@ public class WebClient { log().debug("Sending request:\n{} {}", hreq.method(), hreq.uri()); if (!async) { HttpResponse resp = client().send(hreq, bodyHandler); - log().debug("Received response"); + log().debug("{} response received", resp.statusCode()); return resp; } else { CompletableFuture> future = client().sendAsync(hreq, bodyHandler); future.thenApply(resp -> { - log().debug("Received response"); + log().debug("{} response received", resp.statusCode()); respHandler.accept(resp); return resp; }); @@ -215,6 +252,7 @@ public class WebClient { @SuppressWarnings("unchecked") public HttpResponse post(Consumer configurer) { Request req = new Request(); + req.charset = charset(); configurer.accept(req); HttpRequest hreq = req.post(); @@ -247,6 +285,14 @@ public class WebClient { } } + public String toString(InputStream inputStream) { + try { + return new String(inputStream.readAllBytes(), charset()); + } catch (Exception e) { + throw Assert.runtimeException(e); + } + } + /**전송할 http 요청의 설정. *

Request로 다음 항목들을 설정한다. *

  • {@link #uri(String) uri}: 대상 서버의 uri
  • @@ -295,7 +341,7 @@ public class WebClient { private boolean async, download; - private Charset charset = StandardCharsets.UTF_8; + private Charset charset; private LinkedHashMap headers; private LinkedHashMap keyValues; @@ -357,13 +403,14 @@ public class WebClient { return this; } - /**요청의 문자셋을 설정한다. 디폴트는 UTF-8. - * @param charset 요청의 문자셋 + /**캐시를 사용하지 않도록 헤더를 설정한다. * @return 현재 Request */ - public Request charset(Charset charset) { - this.charset = charset; - return this; + public Request noCache() { + return + header("Cache-Control", "no-cache, no-store, must-revalidate") + .header("Pragma", "no-cache") + .header("Expires", "0"); } /**요청이 비동기인지 설정한다. 디폴트는 false(동기).