Skip to content

Commit 8118342

Browse files
authored
Merge pull request #292 from avaje/feature/http-client-build
[http client] Refactor move DBaseBuilder code into DHttpClientBuilder
2 parents ae2ed58 + a4647f8 commit 8118342

File tree

2 files changed

+163
-183
lines changed

2 files changed

+163
-183
lines changed

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

Lines changed: 0 additions & 181 deletions
This file was deleted.

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

Lines changed: 163 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,174 @@
11
package io.avaje.http.client;
22

3+
import com.fasterxml.jackson.databind.ObjectMapper;
34
import io.avaje.inject.BeanScope;
5+
import io.avaje.jsonb.Jsonb;
46

57
import javax.net.ssl.SSLContext;
68
import javax.net.ssl.SSLParameters;
79
import java.net.Authenticator;
810
import java.net.CookieHandler;
11+
import java.net.CookieManager;
912
import java.net.ProxySelector;
1013
import java.time.Duration;
14+
import java.util.ArrayList;
1115
import java.util.Collections;
16+
import java.util.List;
17+
import java.util.Optional;
1218
import java.util.concurrent.Executor;
1319
import java.util.function.Function;
1420

15-
final class DHttpClientBuilder extends DBaseBuilder implements HttpClient.Builder, HttpClient.Builder.State {
21+
import static java.util.Objects.requireNonNull;
22+
23+
final class DHttpClientBuilder implements HttpClient.Builder, HttpClient.Builder.State {
24+
25+
private java.net.http.HttpClient client;
26+
private String baseUrl;
27+
private boolean requestLogging = true;
28+
private Duration connectionTimeout = Duration.ofSeconds(20);
29+
private Duration requestTimeout = Duration.ofSeconds(20);
30+
private BodyAdapter bodyAdapter;
31+
private RetryHandler retryHandler;
32+
private Function<HttpException, RuntimeException> errorHandler;
33+
private AuthTokenProvider authTokenProvider;
34+
35+
private CookieHandler cookieHandler = new CookieManager();
36+
private java.net.http.HttpClient.Redirect redirect = java.net.http.HttpClient.Redirect.NORMAL;
37+
private java.net.http.HttpClient.Version version;
38+
private Executor executor;
39+
private ProxySelector proxy;
40+
private SSLContext sslContext;
41+
private SSLParameters sslParameters;
42+
private Authenticator authenticator;
43+
private int priority;
44+
45+
private final List<RequestIntercept> interceptors = new ArrayList<>();
46+
private final List<RequestListener> listeners = new ArrayList<>();
47+
48+
private void configureRetryHandler(BeanScope beanScope) {
49+
beanScope.getOptional(RetryHandler.class)
50+
.ifPresent(this::setRetryHandler);
51+
}
52+
53+
private void setRetryHandler(RetryHandler retryHandler) {
54+
this.retryHandler = retryHandler;
55+
}
56+
57+
private void configureBodyAdapter(BeanScope beanScope) {
58+
Optional<BodyAdapter> body = beanScope.getOptional(BodyAdapter.class);
59+
if (body.isPresent()) {
60+
bodyAdapter = body.get();
61+
} else if (beanScope.contains("io.avaje.jsonb.Jsonb")) {
62+
bodyAdapter = new JsonbBodyAdapter(beanScope.get(Jsonb.class));
63+
} else if (beanScope.contains("com.fasterxml.jackson.databind.ObjectMapper")) {
64+
ObjectMapper objectMapper = beanScope.get(ObjectMapper.class);
65+
bodyAdapter = new JacksonBodyAdapter(objectMapper);
66+
}
67+
}
68+
69+
private RequestListener buildListener() {
70+
if (listeners.isEmpty()) {
71+
return null;
72+
} else if (listeners.size() == 1) {
73+
return listeners.get(0);
74+
} else {
75+
return new DRequestListeners(listeners);
76+
}
77+
}
78+
79+
private RequestIntercept buildIntercept() {
80+
if (interceptors.isEmpty()) {
81+
return null;
82+
} else if (interceptors.size() == 1) {
83+
return interceptors.get(0);
84+
} else {
85+
return new DRequestInterceptors(interceptors);
86+
}
87+
}
88+
89+
private java.net.http.HttpClient defaultClient() {
90+
final var builder = java.net.http.HttpClient.newBuilder()
91+
.followRedirects(redirect)
92+
.connectTimeout(connectionTimeout);
93+
94+
if (cookieHandler != null) {
95+
builder.cookieHandler(cookieHandler);
96+
}
97+
if (version != null) {
98+
builder.version(version);
99+
}
100+
if (executor != null) {
101+
builder.executor(executor);
102+
}
103+
if (proxy != null) {
104+
builder.proxy(proxy);
105+
}
106+
if (sslContext != null) {
107+
builder.sslContext(sslContext);
108+
}
109+
if (sslParameters != null) {
110+
builder.sslParameters(sslParameters);
111+
}
112+
if (authenticator != null) {
113+
builder.authenticator(authenticator);
114+
}
115+
if (priority > 0) {
116+
builder.priority(priority);
117+
}
118+
return builder.build();
119+
}
120+
121+
/**
122+
* Create a reasonable default BodyAdapter if avaje-jsonb or Jackson are present.
123+
*/
124+
private BodyAdapter defaultBodyAdapter() {
125+
if (detectJsonb()) {
126+
bodyAdapter = new JsonbBodyAdapter();
127+
} else if (detectJackson()) {
128+
bodyAdapter = new JacksonBodyAdapter();
129+
}
130+
return bodyAdapter;
131+
}
132+
133+
private boolean detectJsonb() {
134+
return detectTypeExists("io.avaje.jsonb.Jsonb");
135+
}
136+
137+
private boolean detectJackson() {
138+
return detectTypeExists("com.fasterxml.jackson.databind.ObjectMapper");
139+
}
140+
141+
private boolean detectTypeExists(String className) {
142+
try {
143+
Class.forName(className);
144+
return true;
145+
} catch (ClassNotFoundException | IllegalAccessError e) {
146+
return false;
147+
}
148+
}
149+
150+
private DHttpClientContext buildClient() {
151+
requireNonNull(baseUrl, "baseUrl is not specified");
152+
requireNonNull(requestTimeout, "requestTimeout is not specified");
153+
final var httpClient = client != null ? client : defaultClient();
154+
if (requestLogging) {
155+
// register the built-in request/response logging
156+
this.listeners.add(new RequestLogger());
157+
}
158+
if (bodyAdapter == null) {
159+
bodyAdapter = defaultBodyAdapter();
160+
}
161+
return new DHttpClientContext(
162+
httpClient,
163+
baseUrl,
164+
requestTimeout,
165+
bodyAdapter,
166+
retryHandler,
167+
errorHandler,
168+
buildListener(),
169+
authTokenProvider,
170+
buildIntercept());
171+
}
16172

17173
DHttpClientBuilder() {
18174
}
@@ -144,7 +300,12 @@ public HttpClient.Builder.State state() {
144300

145301
@Override
146302
public HttpClient.Builder configureWith(BeanScope beanScope) {
147-
super.configureFromScope(beanScope);
303+
if (bodyAdapter == null) {
304+
configureBodyAdapter(beanScope);
305+
}
306+
if (retryHandler == null) {
307+
configureRetryHandler(beanScope);
308+
}
148309
return this;
149310
}
150311

0 commit comments

Comments
 (0)