Skip to content

HttpClientRequest Now Supports Multi-Value Headers/Query Parameters #169

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.net.http.HttpResponse.BodyHandlers.discarding;
Expand Down Expand Up @@ -124,7 +125,25 @@ public HttpClientRequest header(String name, String value) {
}

@Override
public HttpClientRequest header(String name, Collection<String> value) {
if (headers == null) {
headers = new LinkedHashMap<>();
}
headers.computeIfAbsent(name, s -> new ArrayList<>()).addAll(value);
return this;
}

@Override
@SuppressWarnings("unchecked")
public HttpClientRequest header(String name, Object value) {

if (value instanceof Collection) {
final var headerList =
((Collection<Object>) value).stream().map(Object::toString).collect(Collectors.toList());

return header(name, headerList);
}

return value != null ? header(name, value.toString()) : this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.net.http.HttpResponse;
import java.nio.file.Path;
import java.time.Duration;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
Expand Down Expand Up @@ -109,9 +110,10 @@ public interface HttpClientRequest {
HttpClientRequest header(String name, String value);

/**
* Add the header to the request implicitly converting the value to a String.
* Add the header to the request implicitly converting the value to a String. If the value is a
* collection then it's values are appended with the same key
*
* @param name The header name
* @param name The header name
* @param value The header value
* @return The request being built
*/
Expand All @@ -125,6 +127,15 @@ public interface HttpClientRequest {
*/
HttpClientRequest header(Map<String, ?> headers);

/**
* Add the headers to the request via Collection.
*
* @param name The header name
* @param value The header values
* @return The request being built
*/
HttpClientRequest header(String name, Collection<String> value);

/**
* Return the header values that have been set for the given header name.
*
Expand Down Expand Up @@ -218,7 +229,7 @@ public interface HttpClientRequest {
HttpClientRequest queryParam(String name, String value);

/**
* Add a query parameter
* Add a query parameter, if value is a collection then it's values are appended with the same key
*
* @param name The name of the query parameter
* @param value The value of the query parameter which can be null
Expand All @@ -234,6 +245,17 @@ public interface HttpClientRequest {
*/
HttpClientRequest queryParam(Map<String, ?> params);

/**
* Add a query parameter with multiple values
*
* @param name The name of the query parameter
* @param value The values of the query parameter which can be null
* @return The request being built
*/
default HttpClientRequest queryParam(String name, Collection<String> values) {
return queryParam(name, (Object) values);
}

/**
* Add a form parameter.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Map;

/**
Expand Down Expand Up @@ -84,6 +85,14 @@ public UrlBuilder queryParam(String name, String value) {
* The name and value parameters are url encoded.
*/
public UrlBuilder queryParam(String name, Object value) {

if (value instanceof Collection) {
for (var e : (Collection) value) {
queryParam(name, e);
}
return this;
}

if (value != null) {
addQueryParam(name, value.toString());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package io.avaje.http.client;

import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;

import java.time.Duration;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;

class DHttpClientRequestTest {

Expand All @@ -21,6 +22,35 @@ void suppressLogging_listenerEvent_expect_suppressedPayloadContent() {
assertThat(event.responseBody()).isEqualTo("<suppressed response body>");
}

@Test
void assertHeader() {
final var request = new DHttpClientRequest(context, Duration.ZERO);

final var headers =
request
.header("Accept", (Object) List.of("application/json", "application/json2"))
.header("Accept");

assertThat(headers).asList().contains("application/json", "application/json2");
}

@Test
void assertQuery() {
final var client = HttpClient.builder().baseUrl("https://ap7i.github.com").build();

final var uri =
client
.request()
.queryParam("param", List.of("param1", "param2"))
.HEAD()
.asDiscarding()
.request()
.uri()
.toString();

assertThat(uri).isEqualTo("https://ap7i.github.com?param=param1&param=param2");
}

@Test
void skipAuthToken_listenerEvent_expect_suppressedPayloadContent() {
final DHttpClientRequest request = new DHttpClientRequest(context, Duration.ZERO);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -801,7 +801,7 @@ void async_list_as() throws ExecutionException, InterruptedException {
void get_withPathParamAndQueryParam_returningBean() {

final HelloDto dto = clientContext.request()
.path("hello/43/2020-03-05").queryParam("otherParam", "other").queryParam("foo", null)
.path("hello/43/2020-03-05").queryParam("otherParam", "other").queryParam("foo", (Object) null)
.GET()
.bean(HelloDto.class);

Expand All @@ -813,7 +813,7 @@ void get_withPathParamAndQueryParam_returningBean() {
@Test
void callBean() {
final HelloDto dto = clientContext.request()
.path("hello/43/2020-03-05").queryParam("otherParam", "other").queryParam("foo", null)
.path("hello/43/2020-03-05").queryParam("otherParam", "other").queryParam("foo", (Object) null)
.GET()
.call().bean(HelloDto.class).execute();

Expand All @@ -825,7 +825,7 @@ void callBean() {
@Test
void callBeanAsync() throws ExecutionException, InterruptedException {
final CompletableFuture<HelloDto> future = clientContext.request()
.path("hello/43/2020-03-05").queryParam("otherParam", "other").queryParam("foo", null)
.path("hello/43/2020-03-05").queryParam("otherParam", "other").queryParam("foo", (String) null)
.GET()
.call().bean(HelloDto.class).async();

Expand All @@ -842,7 +842,7 @@ void async_whenComplete_returningBean() throws ExecutionException, InterruptedEx
final AtomicReference<HelloDto> ref = new AtomicReference<>();

final CompletableFuture<HelloDto> future = clientContext.request()
.path("hello/43/2020-03-05").queryParam("otherParam", "other").queryParam("foo", null)
.path("hello/43/2020-03-05").queryParam("otherParam", "other").queryParam("foo", (String) null)
.GET()
.async().bean(HelloDto.class);

Expand Down Expand Up @@ -872,7 +872,7 @@ void async_whenComplete_returningBeanWithHeaders() throws ExecutionException, In
final AtomicReference<HttpResponse<HelloDto>> ref = new AtomicReference<>();

final CompletableFuture<HttpResponse<HelloDto>> future = clientContext.request()
.path("hello/43/2020-03-05").queryParam("otherParam", "other").queryParam("foo", null)
.path("hello/43/2020-03-05").queryParam("otherParam", "other").queryParam("foo", (String) null)
.GET()
.async().as(HelloDto.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ void getWithPathParamAndQueryParam() {
assertThat(bean.otherParam).isEqualTo("other");

final HelloDto dto = client.request()
.path("hello/43/2020-03-05").queryParam("otherParam", "other").queryParam("foo", null)
.path("hello/43/2020-03-05").queryParam("otherParam", "other").queryParam("foo", (String) null)
.GET().bean(HelloDto.class);

assertThat(dto.id).isEqualTo(43L);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ void getWithPathParamAndQueryParam() {
assertThat(bean.otherParam).isEqualTo("other");

final HelloDto dto = client.request()
.path("hello/43/2020-03-05").queryParam("otherParam", "other").queryParam("foo", null)
.path("hello/43/2020-03-05").queryParam("otherParam", "other").queryParam("foo", (String) null)
.GET().bean(HelloDto.class);

assertThat(dto.id).isEqualTo(43L);
Expand Down