From 0ae55ea4804e6a7c8bb4257b2a296da2c44691cc Mon Sep 17 00:00:00 2001 From: rprudhvi Date: Tue, 9 Jan 2024 21:40:19 +0530 Subject: [PATCH] [Core] Added Support to set Cookies to WebClient --- .../selcukes/commons/http/WebClient.java | 136 ++++++++++++++---- .../selcukes/commons/tests/WebClientTest.java | 29 +++- .../selcukes/databind/utils/JsonUtils.java | 4 +- 3 files changed, 138 insertions(+), 31 deletions(-) diff --git a/selcukes-commons/src/main/java/io/github/selcukes/commons/http/WebClient.java b/selcukes-commons/src/main/java/io/github/selcukes/commons/http/WebClient.java index 3a9eaca8b..946eb01de 100644 --- a/selcukes-commons/src/main/java/io/github/selcukes/commons/http/WebClient.java +++ b/selcukes-commons/src/main/java/io/github/selcukes/commons/http/WebClient.java @@ -18,19 +18,21 @@ import io.github.selcukes.collections.Resources; import io.github.selcukes.databind.utils.JsonUtils; +import lombok.Singular; import lombok.SneakyThrows; import java.net.InetSocketAddress; import java.net.ProxySelector; +import java.net.URI; +import java.net.URLEncoder; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Base64; -import java.util.Map; -import java.util.UUID; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; import static java.net.http.HttpRequest.BodyPublisher; import static java.net.http.HttpRequest.BodyPublishers; @@ -40,11 +42,64 @@ public class WebClient { private HttpClient.Builder clientBuilder; private HttpRequest.Builder requestBuilder; private BodyPublisher bodyPublisher; + @Singular + private final Map cookies; + @Singular + private final Map queryParams; + private final String baseUri; + private String endpoint; - public WebClient(final String uri) { + public WebClient(String baseUri) { clientBuilder = HttpClient.newBuilder(); - requestBuilder = HttpRequest.newBuilder() - .uri(Resources.toURI(uri)); + requestBuilder = HttpRequest.newBuilder(); + queryParams = new ConcurrentHashMap<>(); + cookies = new ConcurrentHashMap<>(); + this.baseUri = Objects.requireNonNull(baseUri, "baseUri must not be null"); + this.endpoint = ""; + } + + /** + * Sets the endpoint for the request. + * + * @param endpoint The endpoint to set. + * @return The WebClient object. + */ + public WebClient endpoint(String endpoint) { + this.endpoint = endpoint; + return this; + } + + /** + * Adds a cookie to the request. + * + * @param name The name of the cookie. + * @param value The value of the cookie. + * @return The WebClient object. + */ + public WebClient cookie(String name, String value) { + cookies.put(name, value); + return this; + } + + /** + * Sets the body of the request. + * + * @param payload The payload to be set as the request body. + * @return The WebClient object. + */ + public WebClient body(final Object payload) { + this.bodyPublisher = bodyPublisher(payload); + return this; + } + + /** + * This function creates a GET request and executes it. + * + * @return A Response object. + */ + public WebResponse get() { + requestBuilder.GET(); + return execute(); } /** @@ -59,9 +114,10 @@ public WebClient(final String uri) { */ @SneakyThrows public WebResponse post(final Object payload) { - contentType("application/json"); - var request = requestBuilder.POST(bodyPublisher(payload)).build(); - return execute(request); + contentType("application/json") + .body(payload); + requestBuilder.POST(bodyPublisher); + return execute(); } /** @@ -71,8 +127,8 @@ public WebResponse post(final Object payload) { */ @SneakyThrows public WebResponse post() { - var request = requestBuilder.POST(bodyPublisher).build(); - return execute(request); + requestBuilder.POST(bodyPublisher); + return execute(); } /** @@ -81,8 +137,8 @@ public WebResponse post() { * @return A Response object. */ public WebResponse delete() { - var request = requestBuilder.DELETE().build(); - return execute(request); + requestBuilder.DELETE(); + return execute(); } /** @@ -97,8 +153,9 @@ public WebResponse delete() { * @return A Response object */ public WebResponse put(final Object payload) { - var request = requestBuilder.PUT(bodyPublisher(payload)).build(); - return execute(request); + body(payload); + requestBuilder.PUT(bodyPublisher); + return execute(); } @SneakyThrows @@ -141,20 +198,18 @@ private BodyPublisher multiPartBody(final Map data, final String bo } @SneakyThrows - private WebResponse execute(final HttpRequest request) { + private WebResponse execute() { + if (!cookies.isEmpty()) { + String cookieHeader = cookies.entrySet().stream() + .map(entry -> entry.getKey() + "=" + entry.getValue()) + .collect(Collectors.joining("; ")); + requestBuilder = requestBuilder.header("Cookie", cookieHeader); + clientBuilder.followRedirects(HttpClient.Redirect.NORMAL); + } + var request = requestBuilder.uri(buildUri()).build(); return new WebResponse(clientBuilder.build().send(request, ofString())); } - /** - * This function creates a GET request and executes it. - * - * @return A Response object. - */ - public WebResponse get() { - var request = requestBuilder.GET().build(); - return execute(request); - } - /** * If the proxy parameter is a valid URL, then set the proxy host and port * to the host and port of the URL @@ -237,4 +292,31 @@ public WebClient contentType(final String type) { return this; } + /** + * Adds a query parameter to the request. + *

+ * This method allows you to include query parameters in your HTTP request. + * The provided name and value are encoded and added to the query parameters + * map. + *

+ * + * @param name The name of the query parameter. + * @param value The value of the query parameter. + * @return The {@code WebClient} object with the specified query + * parameter added. + */ + public WebClient queryParams(String name, String value) { + queryParams.put(encode(name), encode(value)); + return this; + } + + private String encode(String value) { + return URLEncoder.encode(value, StandardCharsets.UTF_8); + } + + private URI buildUri() { + var joiner = new StringJoiner("&"); + queryParams.forEach((key, value) -> joiner.add(encode(key) + "=" + encode(value))); + return Resources.toURI(baseUri + endpoint + (baseUri.contains("?") ? "&" : "?") + joiner); + } } diff --git a/selcukes-commons/src/test/java/io/github/selcukes/commons/tests/WebClientTest.java b/selcukes-commons/src/test/java/io/github/selcukes/commons/tests/WebClientTest.java index df0022772..c461baabc 100644 --- a/selcukes-commons/src/test/java/io/github/selcukes/commons/tests/WebClientTest.java +++ b/selcukes-commons/src/test/java/io/github/selcukes/commons/tests/WebClientTest.java @@ -53,8 +53,8 @@ public void uploadFileTest() { @Test public void requestTest() { - var client = new WebClient("https://reqres.in/api/users/2"); - var responseBody = client.get().bodyJson(); + var client = new WebClient("https://reqres.in/api"); + var responseBody = client.endpoint("/users/2").get().bodyJson(); assertEquals(responseBody.at("/data/id").asText(), "2"); assertEquals(responseBody.at("/data/first_name").asText(), "Janet"); } @@ -74,4 +74,29 @@ public void authTest() { .get().bodyJson(); assertTrue(responseBody.at("/authenticated").asBoolean()); } + + @Test + public void queryParamTest() { + var perPage = 20; + var client = new WebClient("https://api.github.com"); + var responseBody = client + .queryParams("q", "john") + .queryParams("per_page", String.valueOf(perPage)) + .endpoint("/search/users") + .get().bodyJson(); + var items = responseBody.at("/items"); + assertTrue(items.isArray()); + assertEquals(items.size(), perPage); + + } + + @Test + public void cookieTest() { + var client = new WebClient("https://postman-echo.com/cookies"); + var responseBody = client + .cookie("skill", "1234") + .endpoint("/set") + .get().bodyJson(); + assertEquals(responseBody.at("/cookies/skill").asText(), "1234"); + } } diff --git a/selcukes-databind/src/main/java/io/github/selcukes/databind/utils/JsonUtils.java b/selcukes-databind/src/main/java/io/github/selcukes/databind/utils/JsonUtils.java index f286303fc..e3ca9bacf 100644 --- a/selcukes-databind/src/main/java/io/github/selcukes/databind/utils/JsonUtils.java +++ b/selcukes-databind/src/main/java/io/github/selcukes/databind/utils/JsonUtils.java @@ -30,7 +30,7 @@ public class JsonUtils { * @param object The object to be converted to JSON * @return A JSON string */ - public String toJson(final Object object) { + public String toJson(final T object) { try { return new ObjectMapper().writeValueAsString(object); } catch (Exception e) { @@ -44,7 +44,7 @@ public String toJson(final Object object) { * @param object The object to be converted to JSON * @return A JSON string */ - public String toPrettyJson(final Object object) { + public String toPrettyJson(final T object) { try { return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(object); } catch (Exception e) {