Skip to content

Commit 02900c0

Browse files
committed
Improve Http stub for pre java11 JVMs
1 parent d3287c0 commit 02900c0

File tree

6 files changed

+127
-4
lines changed

6 files changed

+127
-4
lines changed

fallbacks/src/main/java/notjava/net/http/HttpRequest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ public static HttpRequest.Builder newBuilder() {
4848

4949
public abstract String method();
5050

51+
public abstract Optional<Duration> timeout();
52+
5153
public abstract URI uri();
5254

5355
public abstract HttpHeaders headers();

fallbacks/src/main/java/notjava/net/http/HttpResponse.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ public interface HttpResponse<T> {
1818

1919
interface ResponseInfo {
2020
int statusCode();
21+
22+
HttpHeaders headers();
2123
}
2224

2325
@FunctionalInterface

fallbacks/src/main/java/notjava/net/http/impl/HttpClientImpl.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
package notjava.net.http.impl;
22

33
import java.io.IOException;
4+
import java.net.HttpURLConnection;
5+
import java.net.Proxy;
46
import java.net.ProxySelector;
57
import notjava.net.http.HttpClient;
68
import notjava.net.http.HttpRequest;
79
import notjava.net.http.HttpResponse;
810
import notjava.net.http.WebSocket;
911
import java.time.Duration;
12+
import java.util.List;
13+
import java.util.Map;
1014
import java.util.Optional;
1115
import java.util.concurrent.CompletableFuture;
1216

@@ -31,7 +35,42 @@ public Optional<ProxySelector> proxy() {
3135

3236
@Override
3337
public <T> HttpResponse<T> send(HttpRequest request, HttpResponse.BodyHandler<T> responseBodyHandler) throws IOException, InterruptedException {
34-
return null;
38+
HttpURLConnection httpURLConnection;
39+
if (this.proxySelector == Builder.NO_PROXY) {
40+
httpURLConnection = (HttpURLConnection)
41+
request.uri().toURL().openConnection(Proxy.NO_PROXY);
42+
} else {
43+
httpURLConnection = (HttpURLConnection)
44+
request.uri().toURL().openConnection();
45+
}
46+
httpURLConnection.setRequestMethod(request.method());
47+
for (Map.Entry<String, List<String>> entry : request.headers().map().entrySet()) {
48+
for (String value : entry.getValue()) {
49+
httpURLConnection.setRequestProperty(entry.getKey(), value);
50+
}
51+
}
52+
Optional<Duration> timeoutOptional = request.timeout();
53+
if (timeoutOptional.isPresent()) {
54+
httpURLConnection.setConnectTimeout((int) timeoutOptional.get().toMillis());
55+
} else if (this.connectTimeout != null) {
56+
httpURLConnection.setConnectTimeout((int) this.connectTimeout.toMillis());
57+
}
58+
httpURLConnection.setDoInput(true);
59+
Optional<HttpRequest.BodyPublisher> bodyPublisherOptional = request.bodyPublisher();
60+
HttpRequest.BodyPublisher bodyPublisher;
61+
if (bodyPublisherOptional.isPresent()) {
62+
bodyPublisher = bodyPublisherOptional.get();
63+
if (bodyPublisher instanceof ByteArrayBodyPublisherImpl) {
64+
httpURLConnection.setDoOutput(true);
65+
((ByteArrayBodyPublisherImpl) bodyPublisher)
66+
.implDirectWrite(httpURLConnection.getOutputStream());
67+
}
68+
}
69+
HttpResponseImpl<T> httpResponse = new HttpResponseImpl<>(
70+
httpURLConnection, httpURLConnection.getResponseCode());
71+
httpResponse.implRead(httpURLConnection.getInputStream(),
72+
responseBodyHandler);
73+
return httpResponse;
3574
}
3675

3776
@Override

fallbacks/src/main/java/notjava/net/http/impl/HttpRequestBuilderImpl.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,14 @@
1111
public class HttpRequestBuilderImpl implements HttpRequest.Builder {
1212
private final HashMap<String, List<String>> headers = new HashMap<>();
1313
private HttpRequest.BodyPublisher bodyPublisher;
14-
private String method = "GET";
14+
private Duration timeout;
15+
private String method;
1516
private URI uri;
1617

18+
public HttpRequestBuilderImpl() {
19+
this.method = "GET";
20+
}
21+
1722
@Override
1823
public HttpRequest.Builder uri(URI uri) {
1924
this.uri = uri;
@@ -30,6 +35,7 @@ public HttpRequest.Builder header(String name, String value) {
3035

3136
@Override
3237
public HttpRequest.Builder timeout(Duration duration) {
38+
this.timeout = duration;
3339
return this;
3440
}
3541

@@ -71,6 +77,7 @@ public HttpRequest.Builder DELETE() {
7177

7278
@Override
7379
public HttpRequest build() {
74-
return new HttpRequestImpl(this.method, uri, HttpHeaders.of(headers, (k, v) -> true), bodyPublisher);
80+
return new HttpRequestImpl(this.method, this.timeout, this.uri,
81+
HttpHeaders.of(this.headers, (k, v) -> true), this.bodyPublisher);
7582
}
7683
}

fallbacks/src/main/java/notjava/net/http/impl/HttpRequestImpl.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,20 @@
33
import java.net.URI;
44
import notjava.net.http.HttpHeaders;
55
import notjava.net.http.HttpRequest;
6+
7+
import java.time.Duration;
68
import java.util.Optional;
79

810
public class HttpRequestImpl extends HttpRequest {
911
private final String method;
12+
private final Duration timeout;
1013
private final URI uri;
1114
private final HttpHeaders httpHeaders;
1215
private final HttpRequest.BodyPublisher bodyPublisher;
1316

14-
public HttpRequestImpl(String method, URI uri, HttpHeaders httpHeaders, BodyPublisher bodyPublisher) {
17+
public HttpRequestImpl(String method, Duration timeout, URI uri, HttpHeaders httpHeaders, BodyPublisher bodyPublisher) {
1518
this.method = method;
19+
this.timeout = timeout;
1620
this.uri = uri;
1721
this.httpHeaders = httpHeaders;
1822
this.bodyPublisher = bodyPublisher;
@@ -28,6 +32,11 @@ public String method() {
2832
return this.method;
2933
}
3034

35+
@Override
36+
public Optional<Duration> timeout() {
37+
return Optional.empty();
38+
}
39+
3140
@Override
3241
public URI uri() {
3342
return this.uri;
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package notjava.net.http.impl;
2+
3+
import notjava.net.http.HttpHeaders;
4+
import notjava.net.http.HttpResponse;
5+
6+
import java.io.IOException;
7+
import java.io.InputStream;
8+
import java.net.HttpURLConnection;
9+
import java.nio.ByteBuffer;
10+
import java.util.Collections;
11+
import java.util.List;
12+
import java.util.concurrent.CompletableFuture;
13+
14+
public class HttpResponseImpl<T> implements HttpResponse<T>, HttpResponse.ResponseInfo {
15+
private final HttpHeaders httpHeaders;
16+
private final int statusCode;
17+
private CompletableFuture<T> body;
18+
19+
public HttpResponseImpl(HttpURLConnection httpURLConnection, int statusCode) {
20+
this.httpHeaders = HttpHeaders.of(httpURLConnection
21+
.getHeaderFields(), (k, v) -> true);
22+
this.statusCode = statusCode;
23+
}
24+
25+
@Override
26+
public int statusCode() {
27+
return this.statusCode;
28+
}
29+
30+
@Override
31+
public HttpHeaders headers() {
32+
return this.httpHeaders;
33+
}
34+
35+
@Override
36+
public T body() {
37+
return body.join();
38+
}
39+
40+
public void implRead(InputStream inputStream,
41+
HttpResponse.BodyHandler<T> bodyHandler)
42+
throws IOException {
43+
BodySubscriber<T> bodySubscriber = bodyHandler.apply(this);
44+
byte[] buffer = new byte[2048];
45+
List<ByteBuffer> byteBufferList =
46+
Collections.singletonList(
47+
ByteBuffer.wrap(buffer));
48+
int len;
49+
try {
50+
while ((len = inputStream.read(buffer)) > 0) {
51+
if (len == buffer.length) {
52+
bodySubscriber.onNext(byteBufferList);
53+
} else {
54+
bodySubscriber.onNext(Collections.singletonList(
55+
ByteBuffer.wrap(buffer, 0, len)));
56+
}
57+
}
58+
} catch (IOException ioe) {
59+
bodySubscriber.onError(ioe);
60+
throw ioe;
61+
}
62+
this.body = bodySubscriber.getBody().toCompletableFuture();
63+
}
64+
}

0 commit comments

Comments
 (0)