====== Java HttpClient ======
* [[https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpClient.html|java.net.http.HttpClient]]
* Apache 것은 [[java:apache_http_client|Apache Http Client]]
===== 주의 =====
==== 성능 이슈 ====
* Java 17 미만 버전의 Http Client 는 ''synchronized'' 블록이 있어서 일부 상황에서 멀티 쓰레드에서 동시 호출시 문제 발생소지가 있음. Java 17 이상에서는 괜찮음.
* [[https://toss.tech/article/engineering-note-3|Feign 코드 분석과 서버 성능 개선]]
==== 일부 헤더가 사라지는 문제 ====
* 일부 헤더(''connection'', ''content-length'', ''expect'', ''host'', ''upgrade'')가 사라지는 현상이 발생한다.
* 보안을 위해 ''sec-''로 시작되는 헤더도 삭제한다.
* 이것은 문제는 아니고, 의도된 것인데 System Property 를 지정해주면된다. 호출이 일어날 때마다 프라퍼티 확인(Java 16 이후버전)
# 대소문자 안 가림
jdk.httpclient.allowRestrictedHeaders=host,content-length
# sec- 헤더는 이것만으로는 해결이 안됨.
* 참조 : [[https://docs.oracle.com/en/java/javase/17/core/java-networking.html#GUID-86B96A42-74FE-4E7D-8E60-D64A03862083|jdk.httpclient.allowRestrictedHeaders]]
* 헌데, ''java.net.HttpURLConnection'' 를 구현한 ''sun.net.www.protocol.http.HttpURLConnection''구현체에 따르면 ''sun.net.http.allowRestrictedHeaders=true'' 이면 무조건 모든 헤더를 사용 가능하게 허가함. ''sec-'' 도 허가됨.
==== SSL 에서 memory leak ====
* [[https://bugs.openjdk.org/browse/JDK-8212136|[JDK-8212136] Remove finalizer implementation in SSLSocketImpl - Java Bug System]]
* Java 19 미만 버전의 경우 ''SSLSocketImpl'' 이 사용되는 호출(''https'')시에 memory leak 발생
* ''finalzier'' 버그.
===== 인증 / Authentication =====
* [[https://www.baeldung.com/java-httpclient-basic-auth|Java HttpClient Basic Authentication | Baeldung]]
* Basic Auth(''Authorization'' 헤더 설정)
HttpClient client = HttpClient.newBuilder()
.authenticator(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("<사용자명>", "<비번>".toCharArray());
}
})
.build();
* ''Authorization'' 헤더 직접 지정 방식. 단, ''authenticator'' 객체가 지정돼 있으면 ''Authorization'' 헤더 직접 지정은 작동하지 않는다.
* [[https://youtrack.jetbrains.com/issue/IDEA-293550/JDK17-and-IntelliJ-proxys-authenticator-cause-removing-of-Authorization-header-from-HTTP-requests|JDK17 and IntelliJ proxy's authenticator cause removing of "Authorization” header from HTTP requests : IDEA-293550]]
// header 직접 설정방식
private static final String getBasicAuthenticationHeader(String username, String password) {
String valueToEncode = username + ":" + password;
return "Basic " + Base64.getEncoder().encodeToString(valueToEncode.getBytes());
}
HttpRequest request = HttpRequest.newBuilder()
.GET()
.uri(new URI("https://postman-echo.com/basic-auth"))
.header("Authorization", getBasicAuthenticationHeader("<사용자명>", "<비번>"))
.build();
===== Connection Pool =====
* Keep Alive Timeout : System Property ''jdk.httpclient.keepalive.timeout=1200'' (초단위) 로 지정.
* Connection Pool Max Size : System Property ''jdk.httpclient.connectionPoolSize=0'' 0이면 무제한. 갯수로 지정.
* [[https://stackoverflow.com/questions/53617574/how-to-keep-connection-alive-in-java-11-http-client|http2 - How to keep connection alive in Java 11 http client - Stack Overflow]]
* [[https://docs.oracle.com/en/java/javase/17/core/java-networking.html#GUID-86B96A42-74FE-4E7D-8E60-D64A03862083|Java Networking - HTTP Client Properties]]
===== HttpRequestBuilder =====
* ''header(key, value)'' : 헤더를 추가한다.
* ''setHeader(key, value)'' : 헤더를 추가하면서 기존값이 있으면 덮어쓴다.
===== Proxy =====
==== System 설정값 따르기 ====
HttpClient.newBuilder()
.proxy(ProxySelector.getDefault())
.build();
==== 명시적 지정 ====
HttpClient client = HttpClient.newBuilder()
.proxy(ProxySelector.of(new InetSocketAddress("www-proxy.com", 8080)))
.build();
===== 참조 =====
* [[https://developer.ibm.com/technologies/java/tutorials/java-theory-and-practice-3/|Java theory and practice: Explore the new Java SE 11 HTTP Client and WebSocket APIs – Build Smart. Build Secure. IBM Developer]]
* [[https://mkyong.com/java/java-11-httpclient-examples/|Java 11 HttpClient Examples - Mkyong.com]]
* [[https://openjdk.java.net/groups/net/httpclient/intro.html|Introduction to the Java HTTP Client]]
* [[https://openjdk.java.net/groups/net/httpclient/recipes.html|Java HTTP Client - Examples and Recipes]]
* [[https://dzone.com/articles/java-11-standardized-http-client-api|Java 11: Standardized HTTP Client API - DZone Java]]
* [[http://zetcode.com/java/httpclient/|Java 11 HttpClient tutorial - creating HTTP requests in Java with HttpClient]]
* [[https://www.baeldung.com/java-9-http-client|Exploring the New HTTP Client in JDK 11 | Baeldung]]
* [[https://www.youtube.com/watch?v=lAW_NhJ3kqs|(95) The New HTTP Client API in Java 11 - YouTube]]
* [[https://golb.hplar.ch/2019/01/java-11-http-client.html|A closer look at the Java 11 HTTP Client]]
* [[https://ryanharrison.co.uk/2018/09/30/java-11-http-client.html|Java 11 HTTP Client API - Ryan Harrison]] - non blocking io 증명
* [[https://dzone.com/articles/java-11-http-client-api-to-consume-restful-web-ser-1|Java 11 HTTP Client API to Consume Restful Web Service Created Using Spring Boot - DZone Java]]
* [[https://www.javaspecialists.eu/archive/Issue271.html|[JavaSpecialists 271] - HttpClient Executors]]
* [[https://dzone.com/articles/high-concurrency-http-clients-on-the-jvm|High-Concurrency HTTP Clients on the JVM - DZone Performance]]
* [[https://blog.codefx.org/java/http-2-api-tutorial/|Java 11 HTTP/2 API Tutorial - blog@CodeFX]]
* https://www.youtube.com/watch?v=sZSdWq490Vw