Skip to content

Commit f30d1f5

Browse files
committed
#5 - Add HttpClientRequest.url(String url) - ability to replace the base url
1 parent 7202d8c commit f30d1f5

File tree

8 files changed

+180
-2
lines changed

8 files changed

+180
-2
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
package io.avaje.http.client;
22

3+
/**
4+
* Read content as a java type.
5+
*/
36
public interface BodyReader<T> {
47

8+
/**
9+
* Read the content returning it as a java type.
10+
*/
511
T read(BodyContent content);
612

713
}

http-client/client/src/main/java/io/avaje/http/client/DHttpClientRequest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ public HttpClientRequest gzip(boolean gzip) {
7575
return this;
7676
}
7777

78+
@Override
79+
public HttpClientRequest url(String baseUrl) {
80+
url.url(baseUrl);
81+
return this;
82+
}
83+
7884
@Override
7985
public HttpClientRequest path(String path) {
8086
url.path(path);

http-client/client/src/main/java/io/avaje/http/client/HttpClientContext.java

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,40 @@
88

99
/**
1010
* The HTTP client context that we use to build and process requests.
11+
*
12+
* <pre>{@code
13+
*
14+
* HttpClientContext ctx = HttpClientContext.newBuilder()
15+
* .withBaseUrl("http://localhost:8080")
16+
* .withBodyAdapter(new JacksonBodyAdapter(new ObjectMapper()))
17+
* .build();
18+
*
19+
* HelloDto dto = ctx.request()
20+
* .path("hello")
21+
* .queryParam("name", "Rob")
22+
* .queryParam("say", "Ki ora")
23+
* .get()
24+
* .bean(HelloDto.class);
25+
*
26+
* }</pre>
1127
*/
1228
public interface HttpClientContext {
1329

1430
/**
1531
* Return the builder to config and build the client context.
32+
*
33+
* <pre>{@code
34+
*
35+
* HttpClientContext ctx = HttpClientContext.newBuilder()
36+
* .withBaseUrl("http://localhost:8080")
37+
* .withBodyAdapter(new JacksonBodyAdapter(new ObjectMapper()))
38+
* .build();
39+
*
40+
* HttpResponse<String> res = ctx.request()
41+
* .path("hello")
42+
* .get().asString();
43+
*
44+
* }</pre>
1645
*/
1746
static HttpClientContext.Builder newBuilder() {
1847
return new DHttpClientContextBuilder();
@@ -31,6 +60,9 @@ static HttpClientContext.Builder newBuilder() {
3160

3261
/**
3362
* Return the body adapter used by the client context.
63+
* <p>
64+
* This is the body adapter used to convert request and response
65+
* bodies to java types. For example using Jackson with JSON payloads.
3466
*/
3567
BodyAdapter converters();
3668

@@ -70,9 +102,24 @@ static HttpClientContext.Builder newBuilder() {
70102
*/
71103
byte[] decodeContent(String encoding, byte[] content);
72104

73-
74105
/**
75106
* Builds the HttpClientContext.
107+
*
108+
* <pre>{@code
109+
*
110+
* HttpClientContext ctx = HttpClientContext.newBuilder()
111+
* .withBaseUrl("http://localhost:8080")
112+
* .withBodyAdapter(new JacksonBodyAdapter(new ObjectMapper()))
113+
* .build();
114+
*
115+
* HelloDto dto = ctx.request()
116+
* .path("hello")
117+
* .queryParam("name", "Rob")
118+
* .queryParam("say", "Ki ora")
119+
* .get()
120+
* .bean(HelloDto.class);
121+
*
122+
* }</pre>
76123
*/
77124
interface Builder {
78125

@@ -85,6 +132,8 @@ interface Builder {
85132

86133
/**
87134
* Set the base URL to use for requests created from the context.
135+
* <p>
136+
* Note that the base url can be replaced via {@link HttpClientRequest#url(String)}.
88137
*/
89138
Builder withBaseUrl(String baseUrl);
90139

@@ -139,6 +188,21 @@ interface Builder {
139188

140189
/**
141190
* Build and return the context.
191+
*
192+
* <pre>{@code
193+
*
194+
* HttpClientContext ctx = HttpClientContext.newBuilder()
195+
* .withBaseUrl("http://localhost:8080")
196+
* .withBodyAdapter(new JacksonBodyAdapter(new ObjectMapper()))
197+
* .build();
198+
*
199+
* HelloDto dto = ctx.request()
200+
* .path("hello")
201+
* .queryParam("say", "Ki ora")
202+
* .get()
203+
* .bean(HelloDto.class);
204+
*
205+
* }</pre>
142206
*/
143207
HttpClientContext build();
144208
}

http-client/client/src/main/java/io/avaje/http/client/HttpClientRequest.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@
1313
* Largely wraps the standard JDK HttpRequest with additional
1414
* support for converting beans to body content and converting
1515
* beans from response content.
16+
*
17+
* <pre>{@code
18+
*
19+
* HelloDto dto = clientContext.request()
20+
* .path("hello").queryParam("name", "Rob").queryParam("say", "Ki ora")
21+
* .get().bean(HelloDto.class);
22+
*
23+
* }</pre>
24+
*
25+
* @see HttpClientContext
1626
*/
1727
public interface HttpClientRequest {
1828

@@ -42,6 +52,23 @@ public interface HttpClientRequest {
4252
*/
4353
HttpClientRequest gzip(boolean gzip);
4454

55+
/**
56+
* Set the URL to use replacing the base URL.
57+
* <pre>{code
58+
*
59+
* HttpResponse<String> res = clientContext.request()
60+
* .url("http://127.0.0.1:8887")
61+
* .path("hello")
62+
* .get().asString();
63+
*
64+
* }</pre>
65+
*
66+
* @param url The url effectively replacing the base url.
67+
* @return The request being built
68+
* @see HttpClientContext.Builder#withBaseUrl(String)
69+
*/
70+
HttpClientRequest url(String url);
71+
4572
/**
4673
* Add a path segment to the URL.
4774
*

http-client/client/src/main/java/io/avaje/http/client/UrlBuilder.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,46 @@
33
import java.net.URLEncoder;
44
import java.nio.charset.StandardCharsets;
55

6+
/**
7+
* Build a URL typically using a base url and adding path and query parameters.
8+
*/
69
public class UrlBuilder {
710

811
private final StringBuilder buffer = new StringBuilder(100);
912

1013
private boolean hasParams;
1114

15+
/**
16+
* Create with a base url.
17+
*/
1218
public UrlBuilder(String base) {
1319
buffer.append(base);
1420
}
1521

22+
/**
23+
* Set the url. This effectively replaces a base url.
24+
*/
25+
public UrlBuilder url(String url) {
26+
buffer.delete(0, buffer.length());
27+
buffer.append(url);
28+
return this;
29+
}
30+
31+
/**
32+
* Add a path segment to the url.
33+
* <p>
34+
* This includes appending a "/" prefix with the path.
35+
*/
1636
public UrlBuilder path(String path) {
1737
buffer.append("/").append(path);
1838
return this;
1939
}
2040

41+
/**
42+
* Append a query parameter.
43+
* <p>
44+
* The name and value parameters are url encoded.
45+
*/
2146
public UrlBuilder queryParam(String name, String value) {
2247
if (value != null) {
2348
buffer.append(hasParams ? '&' : '?');
@@ -27,20 +52,30 @@ public UrlBuilder queryParam(String name, String value) {
2752
return this;
2853
}
2954

55+
/**
56+
* Append a matrix parameter.
57+
* <p>
58+
* The name and value parameters are url encoded.
59+
*/
3060
public UrlBuilder matrixParam(String name, String value) {
3161
if (value != null) {
3262
buffer.append(';').append(enc(name)).append("=").append(enc(value));
3363
}
3464
return this;
3565
}
3666

67+
/**
68+
* URL encode the value.
69+
*/
3770
public static String enc(String val) {
3871
return URLEncoder.encode(val, StandardCharsets.UTF_8);
3972
}
4073

74+
/**
75+
* Return the full URL.
76+
*/
4177
public String build() {
4278
return buffer.toString();
4379
}
4480

45-
4681
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* Provides a HTTP client with support for adapting body content
3+
* (like JSON) to java types.
4+
* <p>
5+
* Uses the Java http client
6+
*
7+
* <pre>{@code
8+
*
9+
* HttpClientContext ctx = HttpClientContext.newBuilder()
10+
* .withBaseUrl("http://localhost:8080")
11+
* .withBodyAdapter(new JacksonBodyAdapter(new ObjectMapper()))
12+
* .build();
13+
*
14+
* HelloDto dto = ctx.request()
15+
* .path("hello")
16+
* .queryParam("say", "Ki ora")
17+
* .get()
18+
* .bean(HelloDto.class);
19+
*
20+
* }</pre>
21+
*/
22+
package io.avaje.http.client;

http-client/client/src/test/java/io/avaje/http/client/HelloControllerTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,18 @@ void get_helloMessage() {
2828
assertThat(hres.statusCode()).isEqualTo(200);
2929
}
3030

31+
@Test
32+
void get_helloMessage_via_url() {
33+
34+
final HttpResponse<String> hres = clientContext.request()
35+
.url("http://127.0.0.1:8887")
36+
.path("hello").path("message")
37+
.get().asString();
38+
39+
assertThat(hres.body()).contains("hello world");
40+
assertThat(hres.statusCode()).isEqualTo(200);
41+
}
42+
3143
@Test
3244
void get_hello_returningListOfBeans() {
3345

http-client/client/src/test/java/io/avaje/http/client/UrlBuilderTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66

77
class UrlBuilderTest {
88

9+
@Test
10+
void url() {
11+
String url = new UrlBuilder("https://foo").url("http://bar").path("bazz").build();
12+
assertThat(url).isEqualTo("http://bar/bazz");
13+
}
14+
915
@Test
1016
void path() {
1117
assertThat(new UrlBuilder("https://foo").path("bar").build()).isEqualTo("https://foo/bar");

0 commit comments

Comments
 (0)