Skip to content

Commit 3b9be58

Browse files
mstahvvaadin-bot
authored andcommitted
chore: use SDK http client instead of a separate http-client dependency (#16897)
Closes #14538
1 parent 5ec2cd3 commit 3b9be58

File tree

6 files changed

+119
-152
lines changed

6 files changed

+119
-152
lines changed

flow-client/pom.xml

+19
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,25 @@
7777
</exclusion>
7878
</exclusions>
7979
</dependency>
80+
<dependency>
81+
<groupId>org.apache.httpcomponents</groupId>
82+
<artifactId>httpclient</artifactId>
83+
<version>4.5.14</version>
84+
<exclusions>
85+
<exclusion>
86+
<groupId>commons-codec</groupId>
87+
<artifactId>commons-codec</artifactId>
88+
</exclusion>
89+
</exclusions>
90+
<scope>provided</scope>
91+
</dependency>
92+
<!-- Overrides the dependency version of httpclient -->
93+
<dependency>
94+
<groupId>commons-codec</groupId>
95+
<artifactId>commons-codec</artifactId>
96+
<version>1.15</version>
97+
<scope>provided</scope>
98+
</dependency>
8099
<dependency>
81100
<groupId>com.google.gwt</groupId>
82101
<artifactId>gwt-user</artifactId>

flow-server/pom.xml

-17
Original file line numberDiff line numberDiff line change
@@ -130,23 +130,6 @@
130130
<artifactId>commons-compress</artifactId>
131131
<version>1.24.0</version>
132132
</dependency>
133-
<dependency>
134-
<groupId>org.apache.httpcomponents</groupId>
135-
<artifactId>httpclient</artifactId>
136-
<version>4.5.14</version>
137-
<exclusions>
138-
<exclusion>
139-
<groupId>commons-codec</groupId>
140-
<artifactId>commons-codec</artifactId>
141-
</exclusion>
142-
</exclusions>
143-
</dependency>
144-
<!-- Overrides the dependency version of httpclient -->
145-
<dependency>
146-
<groupId>commons-codec</groupId>
147-
<artifactId>commons-codec</artifactId>
148-
<version>1.15</version>
149-
</dependency>
150133
<!-- TESTING DEPENDENCIES -->
151134
<dependency>
152135
<groupId>com.vaadin</groupId>

flow-server/src/main/java/com/vaadin/flow/server/frontend/installer/DefaultFileDownloader.java

+62-110
Original file line numberDiff line numberDiff line change
@@ -16,30 +16,22 @@
1616
package com.vaadin.flow.server.frontend.installer;
1717

1818
import java.io.File;
19-
import java.io.FileOutputStream;
2019
import java.io.IOException;
20+
import java.net.Authenticator;
21+
import java.net.InetSocketAddress;
22+
import java.net.PasswordAuthentication;
23+
import java.net.ProxySelector;
2124
import java.net.URI;
22-
import java.net.URL;
23-
import java.nio.channels.Channels;
24-
import java.nio.channels.ReadableByteChannel;
25+
import java.net.http.HttpClient;
26+
import java.net.http.HttpClient.Redirect;
27+
import java.net.http.HttpClient.Version;
28+
import java.net.http.HttpRequest;
29+
import java.net.http.HttpResponse;
30+
import java.net.http.HttpResponse.BodyHandlers;
31+
import java.nio.file.Path;
32+
import java.time.Duration;
2533

2634
import org.apache.commons.io.FileUtils;
27-
import org.apache.commons.io.FilenameUtils;
28-
import org.apache.http.HttpEntity;
29-
import org.apache.http.HttpHost;
30-
import org.apache.http.auth.AuthScope;
31-
import org.apache.http.auth.UsernamePasswordCredentials;
32-
import org.apache.http.client.AuthCache;
33-
import org.apache.http.client.CredentialsProvider;
34-
import org.apache.http.client.config.RequestConfig;
35-
import org.apache.http.client.methods.CloseableHttpResponse;
36-
import org.apache.http.client.methods.HttpGet;
37-
import org.apache.http.client.protocol.HttpClientContext;
38-
import org.apache.http.impl.auth.BasicScheme;
39-
import org.apache.http.impl.client.BasicAuthCache;
40-
import org.apache.http.impl.client.BasicCredentialsProvider;
41-
import org.apache.http.impl.client.CloseableHttpClient;
42-
import org.apache.http.impl.client.HttpClients;
4335
import org.slf4j.Logger;
4436
import org.slf4j.LoggerFactory;
4537

@@ -53,6 +45,7 @@
5345
* @since
5446
*/
5547
public final class DefaultFileDownloader implements FileDownloader {
48+
5649
public static final String HTTPS_PROTOCOLS = "https.protocols";
5750

5851
private final ProxyConfig proxyConfig;
@@ -99,110 +92,69 @@ public void download(URI downloadURI, File destination, String userName,
9992

10093
private void downloadFile(File destination, URI downloadUri)
10194
throws IOException, DownloadException {
102-
CloseableHttpResponse response = execute(downloadUri);
103-
int statusCode = response.getStatusLine().getStatusCode();
104-
if (statusCode != 200) {
105-
throw new DownloadException(
106-
"Got error code " + statusCode + " from the server.");
107-
}
108-
new File(
109-
FilenameUtils.getFullPathNoEndSeparator(destination.toString()))
110-
.mkdirs();
111-
112-
HttpEntity responseEntity = response.getEntity();
113-
long expected = responseEntity.getContentLength();
114-
try (ReadableByteChannel rbc = Channels
115-
.newChannel(responseEntity.getContent());
116-
FileOutputStream fos = new FileOutputStream(destination)) {
117-
long transferred = fos.getChannel().transferFrom(rbc, 0,
118-
Long.MAX_VALUE);
119-
if (expected > 0 && transferred != expected) {
120-
// Download failed and channel.transferFrom does not rethrow the
121-
// exception
122-
throw new DownloadException(
123-
"Error downloading from " + downloadUri + ". Expected "
124-
+ expected + " bytes but got " + transferred);
125-
}
126-
}
12795

128-
}
96+
HttpClient.Builder clientBuilder = HttpClient.newBuilder()
97+
.version(Version.HTTP_1_1).followRedirects(Redirect.NORMAL);
12998

130-
private CloseableHttpResponse execute(URI requestUri) throws IOException {
131-
CloseableHttpResponse response;
13299
ProxyConfig.Proxy proxy = proxyConfig
133-
.getProxyForUrl(requestUri.toString());
100+
.getProxyForUrl(downloadUri.toString());
101+
134102
if (proxy != null) {
135-
getLogger().info("Downloading via proxy {}", proxy.toString());
136-
return executeViaProxy(proxy, requestUri);
103+
getLogger().debug("Downloading via proxy {}", proxy.toString());
104+
clientBuilder = clientBuilder.proxy(ProxySelector
105+
.of(new InetSocketAddress(proxy.host, proxy.port)));
106+
clientBuilder = clientBuilder.authenticator(new Authenticator() {
107+
@Override
108+
protected PasswordAuthentication getPasswordAuthentication() {
109+
if (getRequestorType() == RequestorType.PROXY) {
110+
return new PasswordAuthentication(proxy.username,
111+
proxy.password.toCharArray());
112+
}
113+
return new PasswordAuthentication(userName,
114+
password.toCharArray());
115+
}
116+
});
137117
} else {
138-
getLogger().info("No proxy was configured, downloading directly");
118+
getLogger().debug("No proxy was configured, downloading directly");
139119
if (userName != null && !userName.isEmpty() && password != null
140120
&& !password.isEmpty()) {
141121
getLogger().info("Using credentials ({})", userName);
142-
// Auth target host
143-
URL aURL = requestUri.toURL();
144-
HttpClientContext localContext = makeLocalContext(aURL);
145-
CredentialsProvider credentialsProvider = makeCredentialsProvider(
146-
aURL.getHost(), aURL.getPort(), userName, password);
147-
response = buildHttpClient(credentialsProvider)
148-
.execute(new HttpGet(requestUri), localContext);
149-
} else {
150-
response = buildHttpClient(null)
151-
.execute(new HttpGet(requestUri));
152-
}
153-
}
154-
return response;
155-
}
122+
clientBuilder = clientBuilder
123+
.authenticator(new Authenticator() {
124+
@Override
125+
protected PasswordAuthentication getPasswordAuthentication() {
126+
return new PasswordAuthentication(userName,
127+
password.toCharArray());
128+
}
129+
});
156130

157-
private CloseableHttpResponse executeViaProxy(ProxyConfig.Proxy proxy,
158-
URI requestUri) throws IOException {
159-
final CloseableHttpClient proxyClient;
160-
if (proxy.useAuthentication()) {
161-
proxyClient = buildHttpClient(makeCredentialsProvider(proxy.host,
162-
proxy.port, proxy.username, proxy.password));
163-
} else {
164-
proxyClient = buildHttpClient(null);
131+
}
165132
}
166133

167-
final HttpHost proxyHttpHost = new HttpHost(proxy.host, proxy.port);
168-
169-
final RequestConfig requestConfig = RequestConfig.custom()
170-
.setProxy(proxyHttpHost).build();
171-
172-
final HttpGet request = new HttpGet(requestUri);
173-
request.setConfig(requestConfig);
134+
HttpClient client = clientBuilder.build();
135+
HttpRequest request = HttpRequest.newBuilder().uri(downloadUri).GET()
136+
.build();
174137

175-
return proxyClient.execute(request);
176-
}
177-
178-
private CloseableHttpClient buildHttpClient(
179-
CredentialsProvider credentialsProvider) {
180-
return HttpClients.custom().disableContentCompression()
181-
.useSystemProperties()
182-
.setDefaultCredentialsProvider(credentialsProvider).build();
183-
}
138+
try {
139+
HttpResponse<Path> response = client.send(request,
140+
BodyHandlers.ofFile(destination.toPath()));
141+
if (response.statusCode() != 200) {
142+
throw new DownloadException("Got error code "
143+
+ response.statusCode() + " from the server.");
144+
}
145+
long expected = response.headers()
146+
.firstValueAsLong("Content-Length").getAsLong();
147+
if (destination.length() != expected) {
148+
throw new DownloadException("Error downloading from "
149+
+ downloadUri + ". Expected " + expected
150+
+ " bytes but got " + destination.length());
151+
}
184152

185-
private CredentialsProvider makeCredentialsProvider(String host, int port,
186-
String username, String password) {
187-
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
188-
credentialsProvider.setCredentials(new AuthScope(host, port),
189-
new UsernamePasswordCredentials(username, password));
190-
return credentialsProvider;
191-
}
153+
} catch (InterruptedException ex) {
154+
Thread.currentThread().interrupt();
155+
throw new RuntimeException(ex);
156+
}
192157

193-
private HttpClientContext makeLocalContext(URL requestUrl) {
194-
// Auth target host
195-
HttpHost target = new HttpHost(requestUrl.getHost(),
196-
requestUrl.getPort(), requestUrl.getProtocol());
197-
// Create AuthCache instance
198-
AuthCache authCache = new BasicAuthCache();
199-
// Generate BASIC scheme object and add it to the local auth cache
200-
BasicScheme basicAuth = new BasicScheme();
201-
authCache.put(target, basicAuth);
202-
// Add AuthCache to the execution context
203-
HttpClientContext localContext = HttpClientContext.create();
204-
localContext.setAuthCache(authCache);
205-
return localContext;
206158
}
207159

208160
private Logger getLogger() {

flow-test-generic/src/main/java/com/vaadin/flow/testutil/ClassesSerializableTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ protected Stream<String> getExcludedPatterns() {
230230
// Node downloader classes
231231
"com\\.vaadin\\.flow\\.server\\.frontend\\.installer\\.DefaultArchiveExtractor",
232232
"com\\.vaadin\\.flow\\.server\\.frontend\\.installer\\.ArchiveExtractor",
233-
"com\\.vaadin\\.flow\\.server\\.frontend\\.installer\\.DefaultFileDownloader",
233+
"com\\.vaadin\\.flow\\.server\\.frontend\\.installer\\.DefaultFileDownloader(\\$.*)?",
234234
"com\\.vaadin\\.flow\\.server\\.frontend\\.installer\\.FileDownloader",
235235
"com\\.vaadin\\.flow\\.server\\.frontend\\.installer\\.NodeInstaller",
236236
"com\\.vaadin\\.flow\\.server\\.frontend\\.installer\\.NodeInstaller\\$InstallData",

vaadin-dev-server/src/main/java/com/vaadin/base/devserver/stats/ProjectHelpers.java

+13-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import java.util.UUID;
2727
import java.util.stream.Stream;
2828

29-
import org.apache.commons.codec.binary.Hex;
3029
import org.apache.commons.io.FileUtils;
3130
import org.slf4j.Logger;
3231
import org.slf4j.LoggerFactory;
@@ -107,14 +106,26 @@ static String createHash(String string) {
107106
MessageDigest md = MessageDigest.getInstance("MD5");
108107
md.update(string.getBytes(StandardCharsets.UTF_8));
109108
byte[] digest = md.digest();
110-
return Hex.encodeHexString(digest);
109+
return toHexString(digest);
111110
} catch (Exception e) {
112111
getLogger().debug("Missing hash algorithm", e);
113112
}
114113
}
115114
return StatisticsConstants.MISSING_DATA;
116115
}
117116

117+
private static String toHexString(byte[] bytes) {
118+
StringBuilder hexString = new StringBuilder();
119+
for (int i = 0; i < bytes.length; i++) {
120+
String hex = Integer.toHexString(0xFF & bytes[i]);
121+
if (hex.length() == 1) {
122+
hexString.append('0');
123+
}
124+
hexString.append(hex);
125+
}
126+
return hexString.toString();
127+
}
128+
118129
/**
119130
* Get the source URL for the project.
120131
* <p>

vaadin-dev-server/src/main/java/com/vaadin/base/devserver/stats/StatisticsSender.java

+24-22
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,11 @@
2222
import com.fasterxml.jackson.core.JsonProcessingException;
2323
import com.fasterxml.jackson.databind.JsonNode;
2424
import com.fasterxml.jackson.databind.node.ObjectNode;
25+
import java.net.URI;
26+
import java.net.http.HttpClient;
27+
import java.net.http.HttpRequest;
28+
import java.net.http.HttpResponse;
2529

26-
import org.apache.http.HttpResponse;
27-
import org.apache.http.HttpStatus;
28-
import org.apache.http.client.HttpClient;
29-
import org.apache.http.client.methods.HttpPost;
30-
import org.apache.http.entity.StringEntity;
31-
import org.apache.http.impl.client.HttpClientBuilder;
32-
import org.apache.http.util.EntityUtils;
3330
import org.slf4j.Logger;
3431
import org.slf4j.LoggerFactory;
3532

@@ -281,20 +278,21 @@ String sendStatistics(ObjectNode json) {
281278
private static ObjectNode postData(String postUrl, String data) {
282279
ObjectNode result;
283280
try {
284-
HttpPost post = new HttpPost(postUrl);
285-
post.addHeader("Content-Type", "application/json");
286-
post.setEntity(new StringEntity(data));
287-
288-
HttpClient client = HttpClientBuilder.create().build();
289-
HttpResponse response = client.execute(post);
290-
String responseStatus = response.getStatusLine().getStatusCode()
291-
+ ": " + response.getStatusLine().getReasonPhrase();
281+
HttpClient client = HttpClient.newHttpClient();
282+
HttpRequest request = HttpRequest.newBuilder()
283+
.uri(URI.create(postUrl))
284+
.POST(HttpRequest.BodyPublishers.ofString(data))
285+
.header("Content-Type", "application/json").build();
286+
287+
HttpResponse<String> response = client.send(request,
288+
HttpResponse.BodyHandlers.ofString());
289+
290+
int statusCode = response.statusCode();
291+
292292
JsonNode jsonResponse = null;
293-
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
294-
String responseString = EntityUtils
295-
.toString(response.getEntity());
293+
if (statusCode == 200) {
296294
jsonResponse = JsonHelpers.getJsonMapper()
297-
.readTree(responseString);
295+
.readTree(response.body());
298296
}
299297

300298
if (jsonResponse != null && jsonResponse.isObject()) {
@@ -304,11 +302,15 @@ private static ObjectNode postData(String postUrl, String data) {
304302
result = JsonHelpers.getJsonMapper().createObjectNode();
305303
}
306304
// Update the status and return the results
307-
result.put(StatisticsConstants.FIELD_LAST_STATUS, responseStatus);
305+
result.put(StatisticsConstants.FIELD_LAST_STATUS,
306+
statusCode + ": "); // TODO is reason phrase needed here
308307
return result;
309308

310-
} catch (IOException e) {
311-
getLogger().debug("Failed to send statistics.", e);
309+
} catch (IOException ex) {
310+
getLogger().debug("Failed to send statistics.", ex);
311+
} catch (InterruptedException ex) {
312+
Thread.currentThread().interrupt();
313+
getLogger().debug("Failed to send statistics.", ex);
312314
}
313315

314316
// Fallback

0 commit comments

Comments
 (0)