1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.search.api.transport;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.net.URI;
24 import java.net.http.HttpClient;
25 import java.net.http.HttpRequest;
26 import java.net.http.HttpResponse;
27 import java.time.Duration;
28 import java.util.AbstractMap;
29 import java.util.Map;
30 import java.util.stream.Collectors;
31
32 import static java.util.Objects.requireNonNull;
33
34
35
36
37 public class Java11HttpClientTransport implements Transport {
38 private static class ResponseImpl implements Response {
39
40 private final HttpResponse<?> response;
41
42 private final InputStream inputStream;
43
44 private ResponseImpl(HttpResponse<?> response, InputStream inputStream) {
45 this.response = requireNonNull(response);
46 this.inputStream = inputStream;
47 }
48
49 @Override
50 public int getCode() {
51 return response.statusCode();
52 }
53
54 @Override
55 public Map<String, String> getHeaders() {
56 return response.headers().map().entrySet().stream()
57 .map(e -> new AbstractMap.SimpleEntry<>(
58 e.getKey(), e.getValue().get(0)))
59 .collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
60 }
61
62 @Override
63 public InputStream getBody() {
64 return inputStream;
65 }
66
67 @Override
68 public void close() throws IOException {
69 if (inputStream != null) {
70 inputStream.close();
71 }
72 }
73 }
74
75 private final Duration timeout;
76
77 private final HttpClient client;
78
79 public Java11HttpClientTransport() {
80 this(Duration.ofSeconds(10L));
81 }
82
83 public Java11HttpClientTransport(Duration timeout) {
84 this(
85 timeout,
86 HttpClient.newBuilder()
87 .connectTimeout(timeout)
88 .followRedirects(HttpClient.Redirect.NEVER)
89 .build());
90 }
91
92 public Java11HttpClientTransport(Duration timeout, HttpClient client) {
93 this.timeout = requireNonNull(timeout);
94 this.client = requireNonNull(client);
95 }
96
97 @Override
98 public Response get(String serviceUri, Map<String, String> headers) throws IOException {
99 HttpRequest.Builder builder = HttpRequest.newBuilder()
100 .timeout(timeout)
101 .uri(URI.create(serviceUri))
102 .GET();
103 for (Map.Entry<String, String> header : headers.entrySet()) {
104 builder.header(header.getKey(), header.getValue());
105 }
106 HttpRequest request = builder.build();
107 try {
108 HttpResponse<InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());
109 return new ResponseImpl(response, response.body());
110 } catch (InterruptedException e) {
111 Thread.currentThread().interrupt();
112 throw new IOException(e);
113 }
114 }
115
116 @Override
117 public Response head(String serviceUri, Map<String, String> headers) throws IOException {
118 HttpRequest.Builder builder = HttpRequest.newBuilder()
119 .timeout(timeout)
120 .uri(URI.create(serviceUri))
121 .method("HEAD", HttpRequest.BodyPublishers.noBody());
122 for (Map.Entry<String, String> header : headers.entrySet()) {
123 builder.header(header.getKey(), header.getValue());
124 }
125 HttpRequest request = builder.build();
126 try {
127 HttpResponse<Void> response = client.send(request, HttpResponse.BodyHandlers.discarding());
128 return new ResponseImpl(response, null);
129 } catch (InterruptedException e) {
130 Thread.currentThread().interrupt();
131 throw new IOException(e);
132 }
133 }
134 }