Skip to content

Commit 5fc3864

Browse files
authored
Add a new "zerodep" transport based on AHC5 (#1404)
1 parent 4fd7bbc commit 5fc3864

File tree

7 files changed

+378
-215
lines changed

7 files changed

+378
-215
lines changed

docker-java-transport-httpclient5/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
<dependency>
3838
<groupId>net.java.dev.jna</groupId>
39-
<artifactId>jna-platform</artifactId>
39+
<artifactId>jna</artifactId>
4040
<version>5.5.0</version>
4141
</dependency>
4242
</dependencies>
Lines changed: 3 additions & 213 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,11 @@
11
package com.github.dockerjava.httpclient5;
22

33
import com.github.dockerjava.transport.SSLConfig;
4-
import com.github.dockerjava.transport.DockerHttpClient;
5-
import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
6-
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
7-
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
8-
import org.apache.hc.client5.http.impl.classic.HttpClients;
9-
import org.apache.hc.client5.http.impl.io.ManagedHttpClientConnectionFactory;
10-
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
11-
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
12-
import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
13-
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
14-
import org.apache.hc.core5.http.ConnectionClosedException;
15-
import org.apache.hc.core5.http.ContentLengthStrategy;
16-
import org.apache.hc.core5.http.Header;
17-
import org.apache.hc.core5.http.HttpHeaders;
18-
import org.apache.hc.core5.http.HttpHost;
19-
import org.apache.hc.core5.http.NameValuePair;
20-
import org.apache.hc.core5.http.config.Registry;
21-
import org.apache.hc.core5.http.config.RegistryBuilder;
22-
import org.apache.hc.core5.http.impl.DefaultContentLengthStrategy;
23-
import org.apache.hc.core5.http.impl.io.EmptyInputStream;
24-
import org.apache.hc.core5.http.io.entity.InputStreamEntity;
25-
import org.apache.hc.core5.http.protocol.BasicHttpContext;
26-
import org.apache.hc.core5.http.protocol.HttpContext;
27-
import org.apache.hc.core5.net.URIAuthority;
28-
import org.slf4j.Logger;
29-
import org.slf4j.LoggerFactory;
304

31-
import javax.net.ssl.SSLContext;
32-
import java.io.IOException;
33-
import java.io.InputStream;
34-
import java.net.Socket;
355
import java.net.URI;
36-
import java.util.List;
37-
import java.util.Map;
386
import java.util.Objects;
39-
import java.util.stream.Collectors;
40-
import java.util.stream.Stream;
417

42-
public final class ApacheDockerHttpClient implements DockerHttpClient {
8+
public final class ApacheDockerHttpClient extends ApacheDockerHttpClientImpl {
439

4410
public static final class Builder {
4511

@@ -63,183 +29,7 @@ public ApacheDockerHttpClient build() {
6329
}
6430
}
6531

66-
private final CloseableHttpClient httpClient;
67-
68-
private final HttpHost host;
69-
70-
private ApacheDockerHttpClient(
71-
URI dockerHost,
72-
SSLConfig sslConfig
73-
) {
74-
Registry<ConnectionSocketFactory> socketFactoryRegistry = createConnectionSocketFactoryRegistry(sslConfig, dockerHost);
75-
76-
switch (dockerHost.getScheme()) {
77-
case "unix":
78-
case "npipe":
79-
host = new HttpHost(dockerHost.getScheme(), "localhost", 2375);
80-
break;
81-
case "tcp":
82-
host = new HttpHost(
83-
socketFactoryRegistry.lookup("https") != null ? "https" : "http",
84-
dockerHost.getHost(),
85-
dockerHost.getPort()
86-
);
87-
break;
88-
default:
89-
host = HttpHost.create(dockerHost);
90-
}
91-
92-
httpClient = HttpClients.custom()
93-
.setRequestExecutor(new HijackingHttpRequestExecutor(null))
94-
.setConnectionManager(new PoolingHttpClientConnectionManager(
95-
socketFactoryRegistry,
96-
new ManagedHttpClientConnectionFactory(
97-
null,
98-
null,
99-
null,
100-
null,
101-
message -> {
102-
Header transferEncodingHeader = message.getFirstHeader(HttpHeaders.TRANSFER_ENCODING);
103-
if (transferEncodingHeader != null) {
104-
if ("identity".equalsIgnoreCase(transferEncodingHeader.getValue())) {
105-
return ContentLengthStrategy.UNDEFINED;
106-
}
107-
}
108-
return DefaultContentLengthStrategy.INSTANCE.determineLength(message);
109-
},
110-
null
111-
)
112-
))
113-
.build();
114-
}
115-
116-
private Registry<ConnectionSocketFactory> createConnectionSocketFactoryRegistry(
117-
SSLConfig sslConfig,
118-
URI dockerHost
119-
) {
120-
RegistryBuilder<ConnectionSocketFactory> socketFactoryRegistryBuilder = RegistryBuilder.create();
121-
122-
if (sslConfig != null) {
123-
try {
124-
SSLContext sslContext = sslConfig.getSSLContext();
125-
if (sslContext != null) {
126-
socketFactoryRegistryBuilder.register("https", new SSLConnectionSocketFactory(sslContext));
127-
}
128-
} catch (Exception e) {
129-
throw new RuntimeException(e);
130-
}
131-
}
132-
133-
return socketFactoryRegistryBuilder
134-
.register("tcp", PlainConnectionSocketFactory.INSTANCE)
135-
.register("http", PlainConnectionSocketFactory.INSTANCE)
136-
.register("unix", new PlainConnectionSocketFactory() {
137-
@Override
138-
public Socket createSocket(HttpContext context) throws IOException {
139-
return new UnixDomainSocket(dockerHost.getPath());
140-
}
141-
})
142-
.register("npipe", new PlainConnectionSocketFactory() {
143-
@Override
144-
public Socket createSocket(HttpContext context) {
145-
return new NamedPipeSocket(dockerHost.getPath());
146-
}
147-
})
148-
.build();
149-
}
150-
151-
@Override
152-
public Response execute(Request request) {
153-
HttpContext context = new BasicHttpContext();
154-
HttpUriRequestBase httpUriRequest = new HttpUriRequestBase(request.method(), URI.create(request.path()));
155-
httpUriRequest.setScheme(host.getSchemeName());
156-
httpUriRequest.setAuthority(new URIAuthority(host.getHostName(), host.getPort()));
157-
158-
request.headers().forEach(httpUriRequest::addHeader);
159-
160-
InputStream body = request.body();
161-
if (body != null) {
162-
httpUriRequest.setEntity(new InputStreamEntity(body, null));
163-
}
164-
165-
if (request.hijackedInput() != null) {
166-
context.setAttribute(HijackingHttpRequestExecutor.HIJACKED_INPUT_ATTRIBUTE, request.hijackedInput());
167-
httpUriRequest.setHeader("Upgrade", "tcp");
168-
httpUriRequest.setHeader("Connection", "Upgrade");
169-
}
170-
171-
try {
172-
CloseableHttpResponse response = httpClient.execute(host, httpUriRequest, context);
173-
174-
return new ApacheResponse(httpUriRequest, response);
175-
} catch (IOException e) {
176-
throw new RuntimeException(e);
177-
}
178-
}
179-
180-
@Override
181-
public void close() throws IOException {
182-
httpClient.close();
183-
}
184-
185-
static class ApacheResponse implements Response {
186-
187-
private static final Logger LOGGER = LoggerFactory.getLogger(ApacheResponse.class);
188-
189-
private final HttpUriRequestBase request;
190-
191-
private final CloseableHttpResponse response;
192-
193-
ApacheResponse(HttpUriRequestBase httpUriRequest, CloseableHttpResponse response) {
194-
this.request = httpUriRequest;
195-
this.response = response;
196-
}
197-
198-
@Override
199-
public int getStatusCode() {
200-
return response.getCode();
201-
}
202-
203-
@Override
204-
public Map<String, List<String>> getHeaders() {
205-
return Stream.of(response.getHeaders()).collect(Collectors.groupingBy(
206-
NameValuePair::getName,
207-
Collectors.mapping(NameValuePair::getValue, Collectors.toList())
208-
));
209-
}
210-
211-
@Override
212-
public String getHeader(String name) {
213-
Header firstHeader = response.getFirstHeader(name);
214-
return firstHeader != null ? firstHeader.getValue() : null;
215-
}
216-
217-
@Override
218-
public InputStream getBody() {
219-
try {
220-
return response.getEntity() != null
221-
? response.getEntity().getContent()
222-
: EmptyInputStream.INSTANCE;
223-
} catch (IOException e) {
224-
throw new RuntimeException(e);
225-
}
226-
}
227-
228-
@Override
229-
public void close() {
230-
try {
231-
request.abort();
232-
} catch (Exception e) {
233-
LOGGER.debug("Failed to abort the request", e);
234-
}
235-
236-
try {
237-
response.close();
238-
} catch (ConnectionClosedException e) {
239-
LOGGER.trace("Failed to close the response", e);
240-
} catch (Exception e) {
241-
LOGGER.debug("Failed to close the response", e);
242-
}
243-
}
32+
private ApacheDockerHttpClient(URI dockerHost, SSLConfig sslConfig) {
33+
super(dockerHost, sslConfig);
24434
}
24535
}

0 commit comments

Comments
 (0)