25 import com.sun.net.httpserver.Headers; |
25 import com.sun.net.httpserver.Headers; |
26 import com.sun.net.httpserver.HttpContext; |
26 import com.sun.net.httpserver.HttpContext; |
27 import com.sun.net.httpserver.HttpExchange; |
27 import com.sun.net.httpserver.HttpExchange; |
28 import com.sun.net.httpserver.HttpHandler; |
28 import com.sun.net.httpserver.HttpHandler; |
29 import com.sun.net.httpserver.HttpServer; |
29 import com.sun.net.httpserver.HttpServer; |
|
30 import jdk.internal.net.http.common.HttpHeadersBuilder; |
30 |
31 |
31 import java.net.InetAddress; |
32 import java.net.InetAddress; |
32 import java.io.ByteArrayInputStream; |
33 import java.io.ByteArrayInputStream; |
33 import java.net.http.HttpClient.Version; |
34 import java.net.http.HttpClient.Version; |
34 import jdk.internal.net.http.common.HttpHeadersImpl; |
|
35 import java.io.ByteArrayOutputStream; |
35 import java.io.ByteArrayOutputStream; |
36 import java.io.IOException; |
36 import java.io.IOException; |
37 import java.io.InputStream; |
37 import java.io.InputStream; |
38 import java.io.OutputStream; |
38 import java.io.OutputStream; |
39 import java.io.PrintStream; |
39 import java.io.PrintStream; |
40 import java.io.UncheckedIOException; |
40 import java.io.UncheckedIOException; |
41 import java.math.BigInteger; |
41 import java.math.BigInteger; |
42 import java.net.InetSocketAddress; |
42 import java.net.InetSocketAddress; |
43 import java.net.URI; |
43 import java.net.URI; |
|
44 import java.net.http.HttpHeaders; |
44 import java.util.List; |
45 import java.util.List; |
45 import java.util.ListIterator; |
46 import java.util.ListIterator; |
46 import java.util.Map; |
47 import java.util.Map; |
47 import java.util.Optional; |
48 import java.util.Optional; |
48 import java.util.Set; |
49 import java.util.Set; |
93 out.println(prefix + bytes.length + " " |
94 out.println(prefix + bytes.length + " " |
94 + new BigInteger(bigbytes).toString(16)); |
95 + new BigInteger(bigbytes).toString(16)); |
95 } |
96 } |
96 |
97 |
97 /** |
98 /** |
98 * A version agnostic adapter class for HTTP Headers. |
99 * A version agnostic adapter class for HTTP request Headers. |
99 */ |
100 */ |
100 public static abstract class HttpTestHeaders { |
101 public static abstract class HttpTestRequestHeaders { |
101 public abstract Optional<String> firstValue(String name); |
102 public abstract Optional<String> firstValue(String name); |
102 public abstract void addHeader(String name, String value); |
|
103 public abstract Set<String> keySet(); |
103 public abstract Set<String> keySet(); |
104 public abstract Set<Map.Entry<String, List<String>>> entrySet(); |
104 public abstract Set<Map.Entry<String, List<String>>> entrySet(); |
105 public abstract List<String> get(String name); |
105 public abstract List<String> get(String name); |
106 public abstract boolean containsKey(String name); |
106 public abstract boolean containsKey(String name); |
107 |
107 |
108 public static HttpTestHeaders of(Headers headers) { |
108 public static HttpTestRequestHeaders of(Headers headers) { |
109 return new Http1TestHeaders(headers); |
109 return new Http1TestRequestHeaders(headers); |
110 } |
110 } |
111 public static HttpTestHeaders of(HttpHeadersImpl headers) { |
111 |
112 return new Http2TestHeaders(headers); |
112 public static HttpTestRequestHeaders of(HttpHeaders headers) { |
113 } |
113 return new Http2TestRequestHeaders(headers); |
114 |
114 } |
115 private final static class Http1TestHeaders extends HttpTestHeaders { |
115 |
|
116 private static final class Http1TestRequestHeaders extends HttpTestRequestHeaders { |
116 private final Headers headers; |
117 private final Headers headers; |
117 Http1TestHeaders(Headers h) { this.headers = h; } |
118 Http1TestRequestHeaders(Headers h) { this.headers = h; } |
118 @Override |
119 @Override |
119 public Optional<String> firstValue(String name) { |
120 public Optional<String> firstValue(String name) { |
120 if (headers.containsKey(name)) { |
121 if (headers.containsKey(name)) { |
121 return Optional.ofNullable(headers.getFirst(name)); |
122 return Optional.ofNullable(headers.getFirst(name)); |
122 } |
123 } |
123 return Optional.empty(); |
124 return Optional.empty(); |
124 } |
125 } |
125 @Override |
126 @Override |
|
127 public Set<String> keySet() { return headers.keySet(); } |
|
128 @Override |
|
129 public Set<Map.Entry<String, List<String>>> entrySet() { |
|
130 return headers.entrySet(); |
|
131 } |
|
132 @Override |
|
133 public List<String> get(String name) { |
|
134 return headers.get(name); |
|
135 } |
|
136 @Override |
|
137 public boolean containsKey(String name) { |
|
138 return headers.containsKey(name); |
|
139 } |
|
140 } |
|
141 private static final class Http2TestRequestHeaders extends HttpTestRequestHeaders { |
|
142 private final HttpHeaders headers; |
|
143 Http2TestRequestHeaders(HttpHeaders h) { this.headers = h; } |
|
144 @Override |
|
145 public Optional<String> firstValue(String name) { |
|
146 return headers.firstValue(name); |
|
147 } |
|
148 @Override |
|
149 public Set<String> keySet() { return headers.map().keySet(); } |
|
150 @Override |
|
151 public Set<Map.Entry<String, List<String>>> entrySet() { |
|
152 return headers.map().entrySet(); |
|
153 } |
|
154 @Override |
|
155 public List<String> get(String name) { |
|
156 return headers.allValues(name); |
|
157 } |
|
158 @Override |
|
159 public boolean containsKey(String name) { |
|
160 return headers.firstValue(name).isPresent(); |
|
161 } |
|
162 } |
|
163 } |
|
164 |
|
165 /** |
|
166 * A version agnostic adapter class for HTTP response Headers. |
|
167 */ |
|
168 public static abstract class HttpTestResponseHeaders { |
|
169 public abstract void addHeader(String name, String value); |
|
170 |
|
171 public static HttpTestResponseHeaders of(Headers headers) { |
|
172 return new Http1TestResponseHeaders(headers); |
|
173 } |
|
174 public static HttpTestResponseHeaders of(HttpHeadersBuilder headersBuilder) { |
|
175 return new Http2TestResponseHeaders(headersBuilder); |
|
176 } |
|
177 |
|
178 private final static class Http1TestResponseHeaders extends HttpTestResponseHeaders { |
|
179 private final Headers headers; |
|
180 Http1TestResponseHeaders(Headers h) { this.headers = h; } |
|
181 @Override |
126 public void addHeader(String name, String value) { |
182 public void addHeader(String name, String value) { |
127 headers.add(name, value); |
183 headers.add(name, value); |
128 } |
184 } |
129 |
185 } |
130 @Override |
186 private final static class Http2TestResponseHeaders extends HttpTestResponseHeaders { |
131 public Set<String> keySet() { return headers.keySet(); } |
187 private final HttpHeadersBuilder headersBuilder; |
132 @Override |
188 Http2TestResponseHeaders(HttpHeadersBuilder hb) { this.headersBuilder = hb; } |
133 public Set<Map.Entry<String, List<String>>> entrySet() { |
|
134 return headers.entrySet(); |
|
135 } |
|
136 @Override |
|
137 public List<String> get(String name) { |
|
138 return headers.get(name); |
|
139 } |
|
140 @Override |
|
141 public boolean containsKey(String name) { |
|
142 return headers.containsKey(name); |
|
143 } |
|
144 } |
|
145 private final static class Http2TestHeaders extends HttpTestHeaders { |
|
146 private final HttpHeadersImpl headers; |
|
147 Http2TestHeaders(HttpHeadersImpl h) { this.headers = h; } |
|
148 @Override |
|
149 public Optional<String> firstValue(String name) { |
|
150 return headers.firstValue(name); |
|
151 } |
|
152 @Override |
189 @Override |
153 public void addHeader(String name, String value) { |
190 public void addHeader(String name, String value) { |
154 headers.addHeader(name, value); |
191 headersBuilder.addHeader(name, value); |
155 } |
|
156 public Set<String> keySet() { return headers.map().keySet(); } |
|
157 @Override |
|
158 public Set<Map.Entry<String, List<String>>> entrySet() { |
|
159 return headers.map().entrySet(); |
|
160 } |
|
161 @Override |
|
162 public List<String> get(String name) { |
|
163 return headers.allValues(name); |
|
164 } |
|
165 @Override |
|
166 public boolean containsKey(String name) { |
|
167 return headers.firstValue(name).isPresent(); |
|
168 } |
192 } |
169 } |
193 } |
170 } |
194 } |
171 |
195 |
172 /** |
196 /** |
175 public static abstract class HttpTestExchange { |
199 public static abstract class HttpTestExchange { |
176 public abstract Version getServerVersion(); |
200 public abstract Version getServerVersion(); |
177 public abstract Version getExchangeVersion(); |
201 public abstract Version getExchangeVersion(); |
178 public abstract InputStream getRequestBody(); |
202 public abstract InputStream getRequestBody(); |
179 public abstract OutputStream getResponseBody(); |
203 public abstract OutputStream getResponseBody(); |
180 public abstract HttpTestHeaders getRequestHeaders(); |
204 public abstract HttpTestRequestHeaders getRequestHeaders(); |
181 public abstract HttpTestHeaders getResponseHeaders(); |
205 public abstract HttpTestResponseHeaders getResponseHeaders(); |
182 public abstract void sendResponseHeaders(int code, int contentLength) throws IOException; |
206 public abstract void sendResponseHeaders(int code, int contentLength) throws IOException; |
183 public abstract URI getRequestURI(); |
207 public abstract URI getRequestURI(); |
184 public abstract String getRequestMethod(); |
208 public abstract String getRequestMethod(); |
185 public abstract void close(); |
209 public abstract void close(); |
186 public void serverPush(URI uri, HttpTestHeaders headers, byte[] body) { |
210 public void serverPush(URI uri, HttpHeaders headers, byte[] body) { |
187 ByteArrayInputStream bais = new ByteArrayInputStream(body); |
211 ByteArrayInputStream bais = new ByteArrayInputStream(body); |
188 serverPush(uri, headers, bais); |
212 serverPush(uri, headers, bais); |
189 } |
213 } |
190 public void serverPush(URI uri, HttpTestHeaders headers, InputStream body) { |
214 public void serverPush(URI uri, HttpHeaders headers, InputStream body) { |
191 throw new UnsupportedOperationException("serverPush with " + getExchangeVersion()); |
215 throw new UnsupportedOperationException("serverPush with " + getExchangeVersion()); |
192 } |
216 } |
193 public boolean serverPushAllowed() { |
217 public boolean serverPushAllowed() { |
194 return false; |
218 return false; |
195 } |
219 } |
284 @Override |
309 @Override |
285 public boolean serverPushAllowed() { |
310 public boolean serverPushAllowed() { |
286 return exchange.serverPushAllowed(); |
311 return exchange.serverPushAllowed(); |
287 } |
312 } |
288 @Override |
313 @Override |
289 public void serverPush(URI uri, HttpTestHeaders headers, InputStream body) { |
314 public void serverPush(URI uri, HttpHeaders headers, InputStream body) { |
290 HttpHeadersImpl headersImpl; |
315 exchange.serverPush(uri, headers, body); |
291 if (headers instanceof HttpTestHeaders.Http2TestHeaders) { |
|
292 headersImpl = ((HttpTestHeaders.Http2TestHeaders)headers).headers.deepCopy(); |
|
293 } else { |
|
294 headersImpl = new HttpHeadersImpl(); |
|
295 for (Map.Entry<String, List<String>> e : headers.entrySet()) { |
|
296 String name = e.getKey(); |
|
297 for (String v : e.getValue()) { |
|
298 headersImpl.addHeader(name, v); |
|
299 } |
|
300 } |
|
301 } |
|
302 exchange.serverPush(uri, headersImpl, body); |
|
303 } |
316 } |
304 void doFilter(Filter.Chain filter) throws IOException { |
317 void doFilter(Filter.Chain filter) throws IOException { |
305 throw new IOException("cannot use HTTP/1.1 filter with HTTP/2 server"); |
318 throw new IOException("cannot use HTTP/1.1 filter with HTTP/2 server"); |
306 } |
319 } |
307 @Override |
320 @Override |