Skip to content

Commit 7c2b4b0

Browse files
max904-githubs-gromov
authored andcommitted
- upgraded Armeria to the latest version 0.99.5 and removed explicit Netty dependency
- reworked ArmeriaHttpClientConfig and added configurations for clientOptions, clientFactory, protocolPreference, retry and logging - added ArmeriaWebClientBuilder to build new WebClient using newWebClient(String scheme, String authority) - adjusted ArmeriaHttpClient and ArmeriaHttpClientTest - added more JavaDoc - removed simplelogger.properties used for tests
1 parent dfbf50d commit 7c2b4b0

File tree

6 files changed

+307
-224
lines changed

6 files changed

+307
-224
lines changed

scribejava-httpclient-armeria/pom.xml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,19 @@
2222
<dependency>
2323
<groupId>com.linecorp.armeria</groupId>
2424
<artifactId>armeria</artifactId>
25-
<version>0.97.0</version>
25+
<version>0.99.5</version>
2626
</dependency>
2727
<dependency>
2828
<groupId>com.github.scribejava</groupId>
29-
<artifactId>scribejava-core</artifactId>
29+
<artifactId>scribejava-apis</artifactId>
3030
<version>${project.version}</version>
31-
<type>test-jar</type>
3231
<scope>test</scope>
3332
</dependency>
3433
<dependency>
35-
<groupId>io.netty</groupId>
36-
<artifactId>netty-all</artifactId>
37-
<version>4.1.43.Final</version>
34+
<groupId>com.github.scribejava</groupId>
35+
<artifactId>scribejava-core</artifactId>
36+
<version>${project.version}</version>
37+
<type>test-jar</type>
3838
<scope>test</scope>
3939
</dependency>
4040
<dependency>

scribejava-httpclient-armeria/src/main/java/com/github/scribejava/httpclient/armeria/ArmeriaHttpClient.java

Lines changed: 54 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,27 @@
11
package com.github.scribejava.httpclient.armeria;
22

3+
import static java.util.Objects.requireNonNull;
4+
35
import com.github.scribejava.core.httpclient.AbstractAsyncOnlyHttpClient;
4-
import com.github.scribejava.core.httpclient.HttpClientConfig;
56
import com.github.scribejava.core.httpclient.multipart.MultipartPayload;
67
import com.github.scribejava.core.httpclient.multipart.MultipartUtils;
78
import com.github.scribejava.core.model.OAuthAsyncRequestCallback;
89
import com.github.scribejava.core.model.OAuthConstants;
910
import com.github.scribejava.core.model.OAuthRequest;
1011
import com.github.scribejava.core.model.Response;
1112
import com.github.scribejava.core.model.Verb;
12-
import com.linecorp.armeria.client.ClientFactory;
13-
import com.linecorp.armeria.client.ClientFactoryBuilder;
14-
import com.linecorp.armeria.client.ClientFactoryOptionValue;
15-
import com.linecorp.armeria.client.ClientOptions;
16-
import com.linecorp.armeria.client.Endpoint;
1713
import com.linecorp.armeria.client.WebClient;
18-
import com.linecorp.armeria.client.WebClientBuilder;
19-
import com.linecorp.armeria.client.logging.LoggingClient;
2014
import com.linecorp.armeria.common.AggregatedHttpResponse;
2115
import com.linecorp.armeria.common.HttpData;
2216
import com.linecorp.armeria.common.HttpMethod;
2317
import com.linecorp.armeria.common.HttpResponse;
2418
import com.linecorp.armeria.common.RequestHeaders;
2519
import com.linecorp.armeria.common.RequestHeadersBuilder;
26-
import com.linecorp.armeria.common.SessionProtocol;
2720

2821
import java.io.File;
2922
import java.io.IOException;
3023
import java.net.URI;
3124
import java.nio.file.Files;
32-
import java.util.Collection;
3325
import java.util.HashMap;
3426
import java.util.Map;
3527
import java.util.concurrent.CompletableFuture;
@@ -38,26 +30,35 @@
3830
import java.util.concurrent.locks.ReentrantReadWriteLock;
3931
import java.util.function.Supplier;
4032

33+
/**
34+
* An implementation of {@link AbstractAsyncOnlyHttpClient} based on
35+
* <a href="https://line.github.io/armeria/">Armeria HTTP client</a>.
36+
*/
4137
public class ArmeriaHttpClient extends AbstractAsyncOnlyHttpClient {
4238

43-
private final ArmeriaHttpClientConfig config;
39+
/**
40+
* A builder of new instances of Armeria's {@link WebClient}
41+
*/
42+
private final ArmeriaWebClientBuilder clientBuilder;
43+
/**
44+
* A list of cached Endpoints. It helps avoiding building a new Endpoint per each request.
45+
*/
4446
private final Map<String, WebClient> httpClients = new HashMap<>();
47+
/**
48+
* A read/write lock to access the list of cached Endpoints concurrently.
49+
*/
4550
private final ReentrantReadWriteLock httpClientsLock = new ReentrantReadWriteLock();
4651

4752
public ArmeriaHttpClient() {
4853
this(ArmeriaHttpClientConfig.defaultConfig());
4954
}
5055

5156
public ArmeriaHttpClient(ArmeriaHttpClientConfig config) {
52-
this.config = config;
53-
}
54-
55-
public HttpClientConfig getConfig() {
56-
return config;
57+
this.clientBuilder = config.builder();
5758
}
5859

5960
/**
60-
* Cleans up HTTP clients collection.
61+
* Cleans up the list of cached Endpoints.
6162
*/
6263
@Override
6364
public void close() {
@@ -112,7 +113,7 @@ private <T> CompletableFuture<T> doExecuteAsync(String userAgent,
112113
final String path = getServicePath(uri);
113114

114115
// Fetch/Create WebClient instance for a given Endpoint
115-
final WebClient client = getHttpClient(uri);
116+
final WebClient client = getClient(uri);
116117

117118
// Build HTTP request
118119
final RequestHeadersBuilder headersBuilder =
@@ -148,55 +149,19 @@ private <T> CompletableFuture<T> doExecuteAsync(String userAgent,
148149
//------------------------------------------------------------------------------------------------
149150

150151
/**
151-
* Extracts Protocol + Host + Port part from a given endpoint {@link URI}
152-
* @param uri an endpoint {@link URI}
153-
* @return a portion of {@link URI} including a combination of Protocol + Host + Port
154-
* @see #getHttpClient(URI uri)
155-
*/
156-
private String getHostUri(final URI uri) {
157-
final StringBuilder builder = new StringBuilder();
158-
builder.append(uri.getScheme()).append("://").append(uri.getHost());
159-
final int port = uri.getPort();
160-
if (port > 0) {
161-
builder.append(":").append(port);
162-
}
163-
return builder.toString();
164-
}
165-
166-
/**
167-
* Extracts service path from a given endpoint {@link URI}
168-
* @param uri an endpoint {@link URI}
169-
* @return service path portion of the {@link URI}
170-
*/
171-
private static String getServicePath(final URI uri) {
172-
final StringBuilder builder = new StringBuilder();
173-
final String path = uri.getRawPath();
174-
if (path != null && path.length() > 0) {
175-
builder.append(path);
176-
} else {
177-
builder.append("/");
178-
}
179-
final String query = uri.getRawQuery();
180-
if (query != null && query.length() > 0) {
181-
builder.append("?").append(query);
182-
}
183-
return builder.toString();
184-
}
185-
186-
/**
187-
* Provides and instance of {@link WebClient} for a given endpoint {@link URI} based on
188-
* a combination of Protocol + Host + Port.
152+
* Provides an instance of {@link WebClient} for a given endpoint {@link URI} based on an endpoint
153+
* as {@code scheme://authority}.
189154
* @param uri an endpoint {@link URI}
190155
* @return {@link WebClient} instance
191156
*/
192-
private WebClient getHttpClient(final URI uri) {
193-
final String hostUri = getHostUri(uri);
157+
private WebClient getClient(final URI uri) {
158+
final String endpoint = getEndPoint(uri);
194159

195160
WebClient client;
196161
final Lock readLock = httpClientsLock.readLock();
197162
readLock.lock();
198163
try {
199-
client = httpClients.get(hostUri);
164+
client = httpClients.get(endpoint);
200165
} finally {
201166
readLock.unlock();
202167
}
@@ -205,88 +170,62 @@ private WebClient getHttpClient(final URI uri) {
205170
return client;
206171
}
207172

208-
client = buildNewHttpClient(uri);
173+
client = clientBuilder.newWebClient(
174+
requireNonNull(uri.getScheme(), "scheme"),
175+
requireNonNull(uri.getAuthority(), "authority"));
209176

210177
final Lock writeLock = httpClientsLock.writeLock();
211178
writeLock.lock();
212179
try {
213-
if (!httpClients.containsKey(hostUri)) {
214-
httpClients.put(hostUri, client);
180+
if (!httpClients.containsKey(endpoint)) {
181+
httpClients.put(endpoint, client);
215182
return client;
216183
} else {
217-
return httpClients.get(hostUri);
184+
return httpClients.get(endpoint);
218185
}
219186
} finally {
220187
writeLock.unlock();
221188
}
222189
}
223190

224191
/**
225-
* Builds a brand-new instance of {@link WebClient} for a given endpoint {@link URI}.
226-
* Uses {@link ArmeriaHttpClientConfig} to configure the builder and the client.
227-
* @param uri an endpoint {@link URI}
228-
* @return Brand-new {@link WebClient} instance
192+
* Extracts {@code scheme} and {@code authority} portion of the {@link URI}.
193+
* Assuming the {@link URI} as the following:
194+
* {@code URI = scheme:[//authority]path[?query][#fragment]}
229195
*/
230-
private WebClient buildNewHttpClient(final URI uri) {
231-
// Build the client and the headers
232-
WebClientBuilder clientBuilder =
233-
getHttpClientBuilder(uri, config.getSessionProtocolPreference());
234-
235-
final ClientOptions clientOptions = config.getClientOptions();
236-
if (clientOptions != null) {
237-
clientBuilder.options(clientOptions);
238-
}
239-
240-
final ClientFactoryBuilder clientFactoryBuilder = ClientFactory.builder();
241-
final Collection<ClientFactoryOptionValue<?>> clientFactoryOptions = config.getClientFactoryOptions();
242-
if (clientFactoryOptions != null && !clientFactoryOptions.isEmpty()) {
243-
clientFactoryOptions.forEach(clientFactoryBuilder::option);
244-
}
245-
clientBuilder.factory(clientFactoryBuilder.build());
246-
247-
if (config.isLogging()) {
248-
clientBuilder = clientBuilder.decorator(LoggingClient.newDecorator());
249-
}
250-
251-
return clientBuilder.build();
196+
@SuppressWarnings("StringBufferReplaceableByString")
197+
private static String getEndPoint(final URI uri) {
198+
final StringBuilder builder = new StringBuilder()
199+
.append(requireNonNull(uri.getScheme(), "scheme"))
200+
.append("://").append(requireNonNull(uri.getAuthority(), "authority"));
201+
return builder.toString();
252202
}
253203

254204
/**
255-
* Provides an instance of {@link WebClientBuilder} for a given endpoint {@link URI}
256-
* @param uri an endpoint {@link URI}
257-
* @param protocolPreference an HTTP protocol generation preference; acceptable values: "h1" or "h2".
258-
* @return {@link WebClientBuilder} instance to build a new {@link WebClient}
205+
* Extracts {@code path}, {@code query) and {@code fragment} portion of the {@link URI}.
206+
* Assuming the {@link URI} as the following:
207+
* {@code URI = scheme:[//authority]path[?query][#fragment]}
259208
*/
260-
private WebClientBuilder getHttpClientBuilder(final URI uri, final SessionProtocol protocolPreference) {
261-
final SessionProtocol sessionProtocol = SessionProtocol.of(uri.getScheme());
262-
final String host = uri.getHost();
263-
final int port = uri.getPort();
264-
final Endpoint endpoint = (port > 0) ? Endpoint.of(host, port) : Endpoint.of(host);
265-
switch(sessionProtocol) {
266-
case HTTP:
267-
if (protocolPreference == SessionProtocol.H1) {
268-
// enforce HTTP/1 protocol
269-
return WebClient.builder(SessionProtocol.H1C, endpoint);
270-
}
271-
break;
272-
case HTTPS:
273-
if (protocolPreference == SessionProtocol.H1) {
274-
// enforce HTTP/1 protocol
275-
return WebClient.builder(SessionProtocol.H1, endpoint);
276-
}
277-
break;
278-
default:
279-
break;
209+
private static String getServicePath(final URI uri) {
210+
final StringBuilder builder = new StringBuilder()
211+
.append(requireNonNull(uri.getPath(), "path"));
212+
final String query = uri.getQuery();
213+
if (query != null) {
214+
builder.append('?').append(query);
280215
}
281-
return WebClient.builder(sessionProtocol, endpoint);
216+
final String fragment = uri.getFragment();
217+
if (fragment != null) {
218+
builder.append('#').append(fragment);
219+
}
220+
return builder.toString();
282221
}
283222

284223
/**
285224
* Maps {@link Verb} to {@link HttpMethod}
286225
* @param httpVerb a {@link Verb} to match with {@link HttpMethod}
287226
* @return {@link HttpMethod} corresponding to the parameter
288227
*/
289-
private HttpMethod getHttpMethod(final Verb httpVerb) {
228+
private static HttpMethod getHttpMethod(final Verb httpVerb) {
290229
switch (httpVerb) {
291230
case GET:
292231
return HttpMethod.GET;

0 commit comments

Comments
 (0)