From 84e115693f6d49b3673c01389906af4bba6c6e19 Mon Sep 17 00:00:00 2001 From: Walter Oggioni Date: Fri, 2 Feb 2024 22:07:32 +0800 Subject: [PATCH] added more classes --- gradle.properties | 2 +- .../java/net/woggioni/jwo/HttpClient.java | 105 ++++++++++++------ src/main/java/net/woggioni/jwo/JWO.java | 3 +- 3 files changed, 76 insertions(+), 34 deletions(-) diff --git a/gradle.properties b/gradle.properties index adf6244..a14b8c2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ -jwo.version = 2024.02.01 +jwo.version = 2024.02.02 lys.version = 2024.02.01 guice.version = 5.0.1 diff --git a/src/main/java/net/woggioni/jwo/HttpClient.java b/src/main/java/net/woggioni/jwo/HttpClient.java index fe35fda..9fde460 100644 --- a/src/main/java/net/woggioni/jwo/HttpClient.java +++ b/src/main/java/net/woggioni/jwo/HttpClient.java @@ -2,22 +2,42 @@ package net.woggioni.jwo; import lombok.AccessLevel; import lombok.Builder; +import lombok.Getter; import lombok.SneakyThrows; +import lombok.ToString; +import org.slf4j.Logger; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import java.io.InputStream; import java.io.OutputStream; +import java.net.CookieManager; +import java.net.CookieStore; +import java.net.HttpCookie; +import java.net.HttpURLConnection; import java.net.URL; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static net.woggioni.jwo.JWO.newThrowable; public class HttpClient { + private static final Logger log = LoggerController.lazyLogger(HttpClient.class); + private static final String COOKIES_HEADER = "Set-Cookie"; + private final CookieStore cookieStore = new CookieManager().getCookieStore(); private SSLSocketFactory socketFactory; + @Getter + private Map> stickyHeaders = new TreeMap<>(); + public HttpClient() {} public HttpClient(final SSLContext sslContext) { @@ -25,15 +45,29 @@ public class HttpClient { } @SneakyThrows - public HttpsURLConnection call(HttpRequest httpRequest) { - HttpsURLConnection conn = (HttpsURLConnection) httpRequest.url.openConnection(); - if(socketFactory != null) { - conn.setSSLSocketFactory(socketFactory); + public HttpURLConnection call(HttpRequest httpRequest) { + HttpURLConnection conn = (HttpURLConnection) httpRequest.url.openConnection(); + + if (socketFactory != null && conn instanceof HttpsURLConnection) { + ((HttpsURLConnection) conn).setSSLSocketFactory(socketFactory); } - conn.setInstanceFollowRedirects(false); + conn.setInstanceFollowRedirects(true); conn.setRequestMethod(httpRequest.method.text); - httpRequest.headers.forEach((key, value) -> - value.forEach(headerValue -> conn.addRequestProperty(key, headerValue))); + Stream.of(stickyHeaders, httpRequest.headers) + .map(Map::entrySet) + .flatMap(Set::stream) + .forEach(entry -> + entry.getValue() + .forEach(headerValue -> + conn.addRequestProperty(entry.getKey(), headerValue))); + List cookies = cookieStore.get(httpRequest.getUrl().toURI()); + if (!cookies.isEmpty()) { + conn.setRequestProperty("Cookie", + cookies.stream() + .map(HttpCookie::toString) + .collect(Collectors.joining(";")) + ); + } switch (httpRequest.method) { case PUT: case POST: @@ -54,6 +88,14 @@ public class HttpClient { case OPTIONS: break; } + conn.getResponseCode(); + Map> headerFields = conn.getHeaderFields(); + List cookiesHeader = headerFields.get(COOKIES_HEADER); + if (cookiesHeader != null) { + for (String cookie : cookiesHeader) { + cookieStore.add(httpRequest.url.toURI(), HttpCookie.parse(cookie).get(0)); + } + } return conn; } @@ -72,54 +114,55 @@ public class HttpClient { } } + @ToString public enum HttpStatus { OK(200), INTERNAL_SERVER_ERROR(500), + SERVICE_UNAVAILABLE(503), BAD_REQUEST(400), UNAUTHORIZED(401), FORBIDDEN(403), NOT_FOUND(404), - CONFLICT(409); + METHOD_NOT_ALLOWED(405), + CONFLICT(409), + UNSUPPORTED_MEDIA_TYPE(415), + GATEWAY_TIMEOUT(504); public final int code; HttpStatus(int code) { this.code = code; } + + public static HttpStatus of(int code) { + return Arrays.stream(values()) + .filter(it -> it.code == code) + .findFirst() + .orElseThrow(() -> newThrowable( + IllegalArgumentException.class, + "HTTP status code %d is not mapped", + code) + ); + } } + @Getter @Builder(builderMethodName = "privateBuilder", access = AccessLevel.PUBLIC) public static class HttpRequest { - final URL url; + private final URL url; - final HttpMethod method = HttpMethod.GET; + @Builder.Default + private final HttpMethod method = HttpMethod.GET; - final Map> headers = Collections.emptyMap(); + @Builder.Default + private final Map> headers = Collections.emptyMap(); - final InputStream body = null; + @Builder.Default + private final InputStream body = null; public static HttpRequestBuilder builder(URL url) { return HttpRequest.privateBuilder().url(url); } - - public static class Builder { - private final URL url; - - private HttpMethod method = HttpMethod.GET; - - private Map> headers = Collections.emptyMap(); - - private InputStream body = null; - - private Builder(URL url) { - this.url = url; - } - - public Builder method(HttpMethod method) { - this.method = method; - return this; - } - } } } diff --git a/src/main/java/net/woggioni/jwo/JWO.java b/src/main/java/net/woggioni/jwo/JWO.java index 1e12abe..aebd449 100644 --- a/src/main/java/net/woggioni/jwo/JWO.java +++ b/src/main/java/net/woggioni/jwo/JWO.java @@ -70,9 +70,8 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; -@Slf4j public class JWO { - + private static final Logger log = LoggerController.lazyLogger(JWO.class); private static final String PROTOCOL_HANDLER = "java.protocol.handler.pkgs"; private static final String HANDLERS_PACKAGE = "net.woggioni.jwo.url";