====== 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