Skip to content

Commit 8ca94a4

Browse files
committed
introduce jedey's poc'
1 parent 43feee4 commit 8ca94a4

3 files changed

Lines changed: 278 additions & 0 deletions

File tree

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package com.google.api.client.http.apache.v3;
2+
3+
import java.io.ByteArrayOutputStream;
4+
import java.io.IOException;
5+
import java.util.concurrent.CompletableFuture;
6+
import java.util.concurrent.ExecutionException;
7+
8+
import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
9+
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
10+
import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder;
11+
import org.apache.hc.client5.http.async.methods.SimpleRequestProducer;
12+
import org.apache.hc.client5.http.async.methods.SimpleResponseConsumer;
13+
import org.apache.hc.client5.http.config.RequestConfig;
14+
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
15+
import org.apache.hc.core5.concurrent.FutureCallback;
16+
import org.apache.hc.core5.http.ContentType;
17+
import org.apache.hc.core5.util.Timeout;
18+
19+
import com.google.api.client.http.LowLevelHttpRequest;
20+
import com.google.api.client.http.LowLevelHttpResponse;
21+
22+
@SuppressWarnings("deprecation")
23+
final class ApacheHttp2Request extends LowLevelHttpRequest {
24+
private final CloseableHttpAsyncClient httpAsyncClient;
25+
private final SimpleRequestBuilder requestBuilder;
26+
private SimpleHttpRequest request;
27+
private final RequestConfig.Builder requestConfig;
28+
29+
ApacheHttp2Request(CloseableHttpAsyncClient httpAsyncClient, SimpleRequestBuilder requestBuilder) {
30+
this.httpAsyncClient = httpAsyncClient;
31+
this.requestBuilder = requestBuilder;
32+
33+
this.requestConfig = RequestConfig.custom()
34+
.setRedirectsEnabled(false);
35+
}
36+
37+
@Override
38+
public void addHeader(String name, String value) {
39+
requestBuilder.addHeader(name, value);
40+
}
41+
42+
@Override
43+
public void setTimeout(int connectionTimeout, int readTimeout) throws IOException {
44+
requestConfig
45+
.setConnectTimeout(Timeout.ofMilliseconds(connectionTimeout))
46+
.setResponseTimeout(Timeout.ofMilliseconds(readTimeout));
47+
// .setConnectionRequestTimeout(connectionTimeout)
48+
// .setResponseTimeout();
49+
}
50+
51+
@Override
52+
public LowLevelHttpResponse execute() throws IOException {
53+
// Convert StreamingContent to bytes to set request body
54+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
55+
getStreamingContent().writeTo(baos);
56+
byte[] bytes = baos.toByteArray();
57+
requestBuilder.setBody(bytes, ContentType.parse(getContentType()));
58+
59+
// Set request configs
60+
requestBuilder.setRequestConfig(requestConfig.build());
61+
62+
// Build and execute request
63+
request = requestBuilder.build();
64+
final CompletableFuture<SimpleHttpResponse> responseFuture = new CompletableFuture<>();
65+
try {
66+
httpAsyncClient.execute(
67+
SimpleRequestProducer.create(request),
68+
SimpleResponseConsumer.create(),
69+
new FutureCallback<SimpleHttpResponse>() {
70+
@Override
71+
public void completed(final SimpleHttpResponse response) {
72+
responseFuture.complete(response);
73+
}
74+
75+
@Override
76+
public void failed(final Exception exception) {
77+
responseFuture.completeExceptionally(exception);
78+
}
79+
80+
@Override
81+
public void cancelled() {
82+
responseFuture.cancel(false);
83+
}
84+
});
85+
final SimpleHttpResponse response = responseFuture.get();
86+
return new ApacheHttp2Response(request, response);
87+
} catch (InterruptedException | ExecutionException e) {
88+
e.printStackTrace();
89+
throw new IOException("Error making request", e);
90+
}
91+
}
92+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package com.google.api.client.http.apache.v3;
2+
3+
import java.io.ByteArrayInputStream;
4+
import java.io.IOException;
5+
import java.io.InputStream;
6+
7+
import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
8+
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
9+
import org.apache.hc.core5.http.Header;
10+
11+
import com.google.api.client.http.LowLevelHttpResponse;
12+
13+
public class ApacheHttp2Response extends LowLevelHttpResponse {
14+
15+
private final SimpleHttpResponse response;
16+
private final Header[] allHeaders;
17+
18+
ApacheHttp2Response(SimpleHttpRequest request, SimpleHttpResponse response) {
19+
this.response = response;
20+
allHeaders = response.getHeaders();
21+
}
22+
23+
@Override
24+
public int getStatusCode() {
25+
return response.getCode();
26+
}
27+
28+
@Override
29+
public InputStream getContent() throws IOException {
30+
return new ByteArrayInputStream(response.getBodyBytes());
31+
}
32+
33+
@Override
34+
public String getContentEncoding() {
35+
return response.getFirstHeader("Content-Encoding").getValue();
36+
}
37+
38+
@Override
39+
public long getContentLength() {
40+
return response.getBodyText().length();
41+
}
42+
43+
@Override
44+
public String getContentType() {
45+
return response.getContentType().toString();
46+
}
47+
48+
@Override
49+
public String getReasonPhrase() {
50+
return response.getReasonPhrase();
51+
}
52+
53+
@Override
54+
public String getStatusLine() {
55+
return response.toString();
56+
}
57+
58+
public String getHeaderValue(String name) {
59+
return response.getLastHeader(name).getValue();
60+
}
61+
62+
@Override
63+
public int getHeaderCount() {
64+
return allHeaders.length;
65+
}
66+
67+
@Override
68+
public String getHeaderName(int index) {
69+
return allHeaders[index].getName();
70+
}
71+
72+
@Override
73+
public String getHeaderValue(int index) {
74+
return allHeaders[index].getValue();
75+
}
76+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package com.google.api.client.http.apache.v3;
2+
3+
import java.io.IOException;
4+
import java.net.ProxySelector;
5+
import java.util.concurrent.TimeUnit;
6+
7+
import org.apache.hc.client5.http.async.HttpAsyncClient;
8+
import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder;
9+
import org.apache.hc.client5.http.config.ConnectionConfig;
10+
import org.apache.hc.client5.http.config.TlsConfig;
11+
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
12+
import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
13+
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
14+
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
15+
import org.apache.hc.client5.http.impl.routing.SystemDefaultRoutePlanner;
16+
import org.apache.hc.client5.http.nio.AsyncClientConnectionManager;
17+
import org.apache.hc.core5.http.config.Http1Config;
18+
import org.apache.hc.core5.http2.HttpVersionPolicy;
19+
import org.apache.hc.core5.http2.config.H2Config;
20+
import org.apache.hc.core5.reactor.IOReactorConfig;
21+
22+
import com.google.api.client.http.HttpTransport;
23+
24+
public final class ApacheHttp2Transport extends HttpTransport{
25+
26+
public final CloseableHttpAsyncClient httpAsyncClient;
27+
28+
public ApacheHttp2Transport() {
29+
this(newDefaultHttpAsyncClient(false));
30+
}
31+
32+
public ApacheHttp2Transport(Boolean useCustom) {
33+
this(newDefaultHttpAsyncClient(useCustom));
34+
}
35+
36+
public ApacheHttp2Transport(CloseableHttpAsyncClient httpAsyncClient) {
37+
this.httpAsyncClient = httpAsyncClient;
38+
httpAsyncClient.start();
39+
}
40+
41+
public static CloseableHttpAsyncClient newDefaultHttpAsyncClient(Boolean useCustom) {
42+
if (useCustom) {
43+
return defaultHttpAsyncClientBuilder().build();
44+
}
45+
return HttpAsyncClients.createHttp2System();
46+
}
47+
48+
public static HttpAsyncClientBuilder defaultHttpAsyncClientBuilder() {
49+
return HttpAsyncClientBuilder.create()
50+
.setH2Config(H2Config.DEFAULT)
51+
.setHttp1Config(Http1Config.DEFAULT)
52+
.setIOReactorConfig(IOReactorConfig.DEFAULT)
53+
.setConnectionManager(defaultAsyncClientConnectionManager())
54+
.setRoutePlanner(new SystemDefaultRoutePlanner(ProxySelector.getDefault()))
55+
.disableRedirectHandling()
56+
.disableAutomaticRetries();
57+
}
58+
59+
public static AsyncClientConnectionManager defaultAsyncClientConnectionManager() {
60+
return defaultPoolingAsyncClientConnectionManagerBuilder()
61+
.build();
62+
}
63+
64+
public static PoolingAsyncClientConnectionManagerBuilder defaultPoolingAsyncClientConnectionManagerBuilder() {
65+
return PoolingAsyncClientConnectionManagerBuilder
66+
.create()
67+
.useSystemProperties()
68+
// .setConnectionConfigResolver(null)
69+
.setDefaultConnectionConfig(defaultConnectionConfig())
70+
// .setTlsConfigResolver(null)
71+
.setDefaultTlsConfig(defaultTlsConfig())
72+
.setTlsStrategy(null)
73+
.setMaxConnTotal(200)
74+
.setMaxConnPerRoute(20);
75+
}
76+
77+
public static TlsConfig defaultTlsConfig() {
78+
return TlsConfig.custom().setVersionPolicy(HttpVersionPolicy.FORCE_HTTP_2).build();
79+
}
80+
81+
public static ConnectionConfig defaultConnectionConfig() {
82+
return ConnectionConfig.custom()
83+
// .setConnectTimeout(null)
84+
// .setSocketTimeout(null)
85+
.setTimeToLive(-1, TimeUnit.MILLISECONDS)
86+
.build();
87+
}
88+
89+
@Override
90+
public boolean supportsMethod(String method) {
91+
return true;
92+
}
93+
94+
@Override
95+
protected ApacheHttp2Request buildRequest(String method, String url) {
96+
SimpleRequestBuilder requestBuilder = SimpleRequestBuilder.create(method).setUri(url);
97+
return new ApacheHttp2Request(httpAsyncClient, requestBuilder);
98+
}
99+
100+
@Override
101+
public void shutdown() throws IOException {
102+
if (httpAsyncClient instanceof CloseableHttpAsyncClient) {
103+
((CloseableHttpAsyncClient) httpAsyncClient).close();
104+
}
105+
}
106+
107+
public HttpAsyncClient getHttpClient() {
108+
return httpAsyncClient;
109+
}
110+
}

0 commit comments

Comments
 (0)