Skip to content
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 @@ -69,6 +69,41 @@ class DHttpClientRequest implements HttpClientRequest, HttpClientResponse {
this.errorMapper = context.errorMapper();
}

private DHttpClientRequest(DHttpClientRequest source) {
this.context = source.context;
this.url = source.url.clone();
this.requestTimeout = source.requestTimeout;
this.gzip = source.gzip;
this.encodedRequestBody = source.encodedRequestBody;
this.body = source.body;
this.httpRequest = source.httpRequest;
this.bodyFormEncoded = source.bodyFormEncoded;
this.loggableResponseBody = source.loggableResponseBody;
this.skipAuthToken = source.skipAuthToken;
this.suppressLogging = source.suppressLogging;
this.label = source.label;
this.errorMapper = source.errorMapper;
this.isRetry = source.isRetry;
this.method = source.method;
if (source.formParams != null) {
this.formParams = new LinkedHashMap<>();
source.formParams.forEach((k,v) -> formParams.put(k, new ArrayList<>(v)));
}
if (source.headers != null) {
this.headers = new LinkedHashMap<>();
source.headers.forEach((k,v) -> headers.put(k, new ArrayList<>(v)));
}
if (source.customAttributes != null) {
// note that the values are not being deep copied here
this.customAttributes = new HashMap<>(source.customAttributes);
}
}

@Override
public HttpClientRequest clone() {
return new DHttpClientRequest(this);
}

@Override
public String method() {
return method;
Expand Down
16 changes: 13 additions & 3 deletions http-client/src/main/java/io/avaje/http/client/DUrlBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,22 @@

final class DUrlBuilder implements UrlBuilder {

private final StringBuilder buffer = new StringBuilder(100);

private final StringBuilder buffer;
private boolean hasParams;

DUrlBuilder(String base) {
buffer.append(base);
this.buffer = new StringBuilder(100);
this.buffer.append(base);
}

private DUrlBuilder(DUrlBuilder source) {
this.hasParams = source.hasParams;
this.buffer = new StringBuilder(source.buffer.toString());
}

@Override
public UrlBuilder clone() {
return new DUrlBuilder(this);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@
*
* @see HttpClient
*/
public interface HttpClientRequest {
public interface HttpClientRequest extends Cloneable {

/**
* Return a copy of the HttpClientRequest.
*/
HttpClientRequest clone();

/**
* For this request skip using an Authorization token.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/**
* Build a URL typically using a base url and adding path and query parameters.
*/
public interface UrlBuilder {
public interface UrlBuilder extends Cloneable {

/**
* URL encode the value.
Expand All @@ -23,6 +23,11 @@ static UrlBuilder of(String baseUrl) {
return new DUrlBuilder(baseUrl);
}

/**
* Return a copy of the UrlBuilder.
*/
UrlBuilder clone();

/**
* Set the url. This effectively replaces a base url.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,54 @@ void suppressLogging_listenerEvent_expect_suppressedPayloadContent() {
assertThat(event.responseBody()).isEqualTo("<suppressed response body>");
}

@Test
void clone_expect_deepCopiesOfOriginalRequest() {
final DHttpClientRequest request = new DHttpClientRequest(context, Duration.ZERO);
request.suppressLogging();
request.path("patha");
request.queryParam("queryParam", "b");
request.header("aheader", "orig");
request.body("SomeBody");
request.setAttribute("foo", "one");
request.formParam("fp", "1");
request.formParam("fp", "2");

HttpClientRequest req0 = request.clone();
HttpClientRequest req1 = request.clone();

request.queryParam("orig", "x");
req0.queryParam("req0", "y");
req1.queryParam("req1", "z");

request.header("aheader", "x");
req0.header("aheader", "y");
req0.formParam("fp2", "5");

req1.header("aheader", "z");
req1.header("req1", "2");
req1.setAttribute("bar", "two");
req1.formParam("fp", "3");

assertThat(request.url()).isEqualTo("null/patha?queryParam=b&orig=x");
assertThat(req0.url()).isEqualTo("null/patha?queryParam=b&req0=y");
assertThat(req1.url()).isEqualTo("null/patha?queryParam=b&req1=z");

assertThat(request.headers()).containsOnlyKeys("aheader");
assertThat(request.header("aheader")).containsOnly("orig", "x");

assertThat(req0.headers()).containsOnlyKeys("aheader");
assertThat(req0.header("aheader")).containsOnly("orig", "y");

assertThat(req1.headers()).containsOnlyKeys("aheader", "req1");
assertThat(req1.header("aheader")).containsOnly("orig", "z");

assertThat((String)req0.getAttribute("foo")).isEqualTo("one");
assertThat((String)req0.getAttribute("bar")).isNull();

assertThat((String)req1.getAttribute("foo")).isEqualTo("one");
assertThat((String)req1.getAttribute("bar")).isEqualTo("two");
}

@Test
void assertHeader() {
final var request = new DHttpClientRequest(context, Duration.ZERO);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,31 @@

class DUrlBuilderTest {

@Test
void clone_expect_copyOfOriginal() {
var uriBuilder = UrlBuilder.of("http://foo")
.path("more");

UrlBuilder copy = uriBuilder.clone();
copy.queryParam("a", "a");

uriBuilder.queryParam("b", "b");
assertThat(uriBuilder.build()).isEqualTo("http://foo/more?b=b");
assertThat(copy.build()).isEqualTo("http://foo/more?a=a");
}

@Test
void clone_hasParams_expect_copyOfOriginal() {
var uriBuilder = UrlBuilder.of("http://foo").path("more").queryParam("orig",1);

UrlBuilder copy = uriBuilder.clone();
copy.queryParam("a", "a");

uriBuilder.queryParam("b", "b");
assertThat(uriBuilder.build()).isEqualTo("http://foo/more?orig=1&b=b");
assertThat(copy.build()).isEqualTo("http://foo/more?orig=1&a=a");
}

@Test
void url() {
var uri = UrlBuilder.of("http://foo")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,28 @@ void post_bean_returningBean_usingExplicitConverters() {
assertEquals(12, bean.id);
}

@Test
void post_bean_clone() {
final BodyWriter from = clientContext.bodyAdapter().beanWriter(HelloDto.class);
final BodyReader<HelloDto> toDto = clientContext.bodyAdapter().beanReader(HelloDto.class);

final HelloDto dto0 = new HelloDto(12, "rob", "other");
HttpClientRequest origReq = clientContext.request()
.path("hello")
.body(from.write(dto0));

final HelloDto dto1 = new HelloDto(13, "bor", "rehto");
HttpClientRequest copyReq = origReq.clone().body(from.write(dto1));

var res0 = origReq.POST().read(toDto);
var res1 = copyReq.POST().read(toDto);

assertEquals("posted", res0.name);
assertEquals(12, res0.id);
assertEquals("posted", res1.name);
assertEquals(13, res1.id);
}

@Test
void post_bean_returningVoid() {

Expand Down