1 /* |
1 /* |
2 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. |
7 * published by the Free Software Foundation. |
18 * |
18 * |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 * or visit www.oracle.com if you need additional information or have any |
20 * or visit www.oracle.com if you need additional information or have any |
21 * questions. |
21 * questions. |
22 */ |
22 */ |
|
23 |
|
24 import com.sun.net.httpserver.HttpServer; |
23 |
25 |
24 import java.io.Closeable; |
26 import java.io.Closeable; |
25 import java.io.IOException; |
27 import java.io.IOException; |
26 import java.io.InputStream; |
28 import java.io.InputStream; |
27 import java.io.OutputStream; |
29 import java.io.OutputStream; |
28 import javax.net.ServerSocketFactory; |
30 import javax.net.ServerSocketFactory; |
29 import javax.net.ssl.SSLServerSocket; |
31 import javax.net.ssl.SSLServerSocket; |
|
32 import java.net.InetAddress; |
|
33 import java.net.InetSocketAddress; |
30 import java.net.ServerSocket; |
34 import java.net.ServerSocket; |
31 import java.net.Socket; |
35 import java.net.Socket; |
32 import java.nio.charset.StandardCharsets; |
36 import java.nio.charset.StandardCharsets; |
33 import java.util.Collections; |
37 import java.util.Collections; |
34 import java.util.LinkedList; |
38 import java.util.LinkedList; |
35 import java.util.List; |
39 import java.util.List; |
36 import java.util.Iterator; |
40 import java.util.Iterator; |
37 import java.util.concurrent.ArrayBlockingQueue; |
41 import java.util.concurrent.ArrayBlockingQueue; |
38 import java.util.concurrent.TimeUnit; |
42 import java.util.concurrent.TimeUnit; |
39 import java.util.concurrent.atomic.AtomicInteger; |
43 import java.util.concurrent.atomic.AtomicInteger; |
|
44 import static java.nio.charset.StandardCharsets.ISO_8859_1; |
40 |
45 |
41 /** |
46 /** |
42 * A cut-down Http/1 Server for testing various error situations |
47 * A cut-down Http/1 Server for testing various error situations |
43 * |
48 * |
44 * use interrupt() to halt |
49 * use interrupt() to halt |
58 // (external) clients that might be lurking |
63 // (external) clients that might be lurking |
59 // on the test machine instead of answering |
64 // on the test machine instead of answering |
60 // to the test client. |
65 // to the test client. |
61 final String root; |
66 final String root; |
62 |
67 |
63 // waits up to 20 seconds for something to happen |
68 // waits up to 2000 seconds for something to happen |
64 // dont use this unless certain activity coming. |
69 // dont use this unless certain activity coming. |
65 public Connection activity() { |
70 public Connection activity() { |
66 for (int i = 0; i < 80 * 100; i++) { |
71 for (int i = 0; i < 80 * 100; i++) { |
67 doRemovalsAndAdditions(); |
72 doRemovalsAndAdditions(); |
68 for (Connection c : sockets) { |
73 for (Connection c : sockets) { |
158 int n = is.read(buf); |
163 int n = is.read(buf); |
159 if (n == -1) { |
164 if (n == -1) { |
160 cleanup(); |
165 cleanup(); |
161 return; |
166 return; |
162 } |
167 } |
163 String s0 = new String(buf, 0, n, StandardCharsets.ISO_8859_1); |
168 String s0 = new String(buf, 0, n, ISO_8859_1); |
164 s = s + s0; |
169 s = s + s0; |
165 int i; |
170 int i; |
166 while ((i=s.indexOf(CRLF)) != -1) { |
171 while ((i=s.indexOf(CRLF)) != -1) { |
167 String s1 = s.substring(0, i+2); |
172 String s1 = s.substring(0, i+2); |
168 System.out.println("Server got: " + s1.substring(0,i)); |
173 System.out.println("Server got: " + s1.substring(0,i)); |
193 { |
198 { |
194 String r1 = "HTTP/1.1 " + Integer.toString(code) + " status" + CRLF; |
199 String r1 = "HTTP/1.1 " + Integer.toString(code) + " status" + CRLF; |
195 for (int i=0; i<headers.length; i+=2) { |
200 for (int i=0; i<headers.length; i+=2) { |
196 r1 += headers[i] + ": " + headers[i+1] + CRLF; |
201 r1 += headers[i] + ": " + headers[i+1] + CRLF; |
197 } |
202 } |
198 int clen = body == null ? 0 : body.length(); |
203 int clen = body == null ? 0 : body.getBytes(ISO_8859_1).length; |
199 r1 += "Content-Length: " + Integer.toString(clen) + CRLF; |
204 r1 += "Content-Length: " + Integer.toString(clen) + CRLF; |
200 r1 += CRLF; |
205 r1 += CRLF; |
201 if (body != null) { |
206 if (body != null) { |
202 r1 += body; |
207 r1 += body; |
203 } |
208 } |
206 |
211 |
207 // content-length is 10 bytes too many |
212 // content-length is 10 bytes too many |
208 public void sendIncompleteHttpResponseBody(int code) throws IOException { |
213 public void sendIncompleteHttpResponseBody(int code) throws IOException { |
209 String body = "Hello World Helloworld Goodbye World"; |
214 String body = "Hello World Helloworld Goodbye World"; |
210 String r1 = "HTTP/1.1 " + Integer.toString(code) + " status" + CRLF; |
215 String r1 = "HTTP/1.1 " + Integer.toString(code) + " status" + CRLF; |
211 int clen = body.length() + 10; |
216 int clen = body.getBytes(ISO_8859_1).length + 10; |
212 r1 += "Content-Length: " + Integer.toString(clen) + CRLF; |
217 r1 += "Content-Length: " + Integer.toString(clen) + CRLF; |
213 r1 += CRLF; |
218 r1 += CRLF; |
214 if (body != null) { |
219 if (body != null) { |
215 r1 += body; |
220 r1 += body; |
216 } |
221 } |
223 String r1 = "HTTP/1.1 " + Integer.toString(code) + " status" + CRLF; |
228 String r1 = "HTTP/1.1 " + Integer.toString(code) + " status" + CRLF; |
224 send(r1); |
229 send(r1); |
225 } |
230 } |
226 |
231 |
227 public void send(String r) throws IOException { |
232 public void send(String r) throws IOException { |
228 os.write(r.getBytes(StandardCharsets.ISO_8859_1)); |
233 try { |
|
234 os.write(r.getBytes(ISO_8859_1)); |
|
235 } catch (IOException x) { |
|
236 IOException suppressed = |
|
237 new IOException("MockServer[" |
|
238 + ss.getLocalPort() |
|
239 +"] Failed while writing bytes: " |
|
240 + x.getMessage()); |
|
241 x.addSuppressed(suppressed); |
|
242 System.err.println("WARNING: " + suppressed); |
|
243 throw x; |
|
244 } |
229 } |
245 } |
230 |
246 |
231 public synchronized void close() { |
247 public synchronized void close() { |
232 cleanup(); |
248 cleanup(); |
233 closed = true; |
249 closed = true; |
273 } |
289 } |
274 } |
290 } |
275 } |
291 } |
276 |
292 |
277 MockServer(int port, ServerSocketFactory factory, String root) throws IOException { |
293 MockServer(int port, ServerSocketFactory factory, String root) throws IOException { |
278 ss = factory.createServerSocket(port); |
294 ss = factory.createServerSocket(); |
|
295 ss.setReuseAddress(false); |
|
296 ss.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); |
279 this.root = root; // if specified, any request which don't have this value |
297 this.root = root; // if specified, any request which don't have this value |
280 // in their statusLine will be rejected. |
298 // in their statusLine will be rejected. |
281 sockets = Collections.synchronizedList(new LinkedList<>()); |
299 sockets = Collections.synchronizedList(new LinkedList<>()); |
282 removals = new LinkedList<>(); |
300 removals = new LinkedList<>(); |
283 additions = new LinkedList<>(); |
301 additions = new LinkedList<>(); |
299 |
317 |
300 int port() { |
318 int port() { |
301 return ss.getLocalPort(); |
319 return ss.getLocalPort(); |
302 } |
320 } |
303 |
321 |
|
322 String serverAuthority() { |
|
323 return InetAddress.getLoopbackAddress().getHostName() + ":" + port(); |
|
324 } |
|
325 |
304 public String getURL() { |
326 public String getURL() { |
305 if (ss instanceof SSLServerSocket) { |
327 if (ss instanceof SSLServerSocket) { |
306 return "https://127.0.0.1:" + port() + "/foo/"; |
328 return "https://" + serverAuthority() + "/foo/"; |
307 } else { |
329 } else { |
308 return "http://127.0.0.1:" + port() + "/foo/"; |
330 return "http://" + serverAuthority() + "/foo/"; |
309 } |
331 } |
310 } |
332 } |
311 |
333 |
312 private volatile boolean closed; |
334 private volatile boolean closed; |
313 |
335 |