|
|
|
@ -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,7 +173,10 @@ public class WebClient {
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private HttpClient client;
|
|
|
|
|
|
|
|
|
|
private HttpClient client() {
|
|
|
|
|
if (client == null) {
|
|
|
|
|
HttpClient.Builder builder = HttpClient.newBuilder()
|
|
|
|
|
.version(version)
|
|
|
|
|
.connectTimeout(timeout)
|
|
|
|
@ -158,7 +189,12 @@ public class WebClient {
|
|
|
|
|
if (proxy != null)
|
|
|
|
|
builder.proxy(proxy);
|
|
|
|
|
|
|
|
|
|
return builder.build();
|
|
|
|
|
if (cookieHandler != null)
|
|
|
|
|
builder.cookieHandler(cookieHandler);
|
|
|
|
|
|
|
|
|
|
client = builder.build();
|
|
|
|
|
}
|
|
|
|
|
return client;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**"GET" 방식의 요청을 전송한다.
|
|
|
|
@ -169,6 +205,7 @@ public class WebClient {
|
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
|
public <T> HttpResponse<T> get(Consumer<Request> 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<T> resp = client().send(hreq, bodyHandler);
|
|
|
|
|
log().debug("Received response");
|
|
|
|
|
log().debug("{} response received", resp.statusCode());
|
|
|
|
|
return resp;
|
|
|
|
|
} else {
|
|
|
|
|
CompletableFuture<HttpResponse<T>> 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 <T> HttpResponse<T> post(Consumer<Request> 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 요청의 설정.
|
|
|
|
|
* <p>Request로 다음 항목들을 설정한다.
|
|
|
|
|
* <ul><li>{@link #uri(String) uri}: 대상 서버의 uri</li>
|
|
|
|
@ -295,7 +341,7 @@ public class WebClient {
|
|
|
|
|
private boolean
|
|
|
|
|
async,
|
|
|
|
|
download;
|
|
|
|
|
private Charset charset = StandardCharsets.UTF_8;
|
|
|
|
|
private Charset charset;
|
|
|
|
|
private LinkedHashMap<String, String> headers;
|
|
|
|
|
private LinkedHashMap<String, Object> 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(동기).
|
|
|
|
|