< prev index next >
test/jdk/java/net/httpclient/SmokeTest.java
Print this page
@@ -30,27 +30,27 @@
* @library /lib/testlibrary/ /
* @build jdk.testlibrary.SimpleSSLContext ProxyServer
* @compile ../../../com/sun/net/httpserver/LogFilter.java
* @compile ../../../com/sun/net/httpserver/EchoHandler.java
* @compile ../../../com/sun/net/httpserver/FileServerHandler.java
- * @run main/othervm -Djdk.httpclient.HttpClient.log=errors,trace SmokeTest
+ * @run main/othervm -Djdk.internal.httpclient.debug=true -Djdk.httpclient.HttpClient.log=errors,trace SmokeTest
*/
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsParameters;
import com.sun.net.httpserver.HttpsServer;
+import java.net.Proxy;
+import java.net.SocketAddress;
import java.util.concurrent.atomic.AtomicInteger;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.ProxySelector;
-import java.net.ServerSocket;
-import java.net.Socket;
import java.net.URI;
import jdk.incubator.http.HttpClient;
import jdk.incubator.http.HttpRequest;
import jdk.incubator.http.HttpResponse;
import java.nio.file.StandardOpenOption;
@@ -79,13 +79,13 @@
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import jdk.testlibrary.SimpleSSLContext;
-import static jdk.incubator.http.HttpRequest.BodyProcessor.fromFile;
-import static jdk.incubator.http.HttpRequest.BodyProcessor.fromInputStream;
-import static jdk.incubator.http.HttpRequest.BodyProcessor.fromString;
+import static jdk.incubator.http.HttpRequest.BodyPublisher.fromFile;
+import static jdk.incubator.http.HttpRequest.BodyPublisher.fromInputStream;
+import static jdk.incubator.http.HttpRequest.BodyPublisher.fromString;
import static jdk.incubator.http.HttpResponse.*;
import static jdk.incubator.http.HttpResponse.BodyHandler.asFile;
import static jdk.incubator.http.HttpResponse.BodyHandler.asString;
import java.util.concurrent.CountDownLatch;
import java.util.logging.ConsoleHandler;
@@ -170,11 +170,10 @@
.sslParameters(sslparams)
.followRedirects(HttpClient.Redirect.ALWAYS)
.build();
try {
-
test1(httproot + "files/foo.txt", true);
test1(httproot + "files/foo.txt", false);
test1(httpsroot + "files/foo.txt", true);
test1(httpsroot + "files/foo.txt", false);
@@ -253,11 +252,14 @@
HttpResponse<String> response = client.send(request, asString());
String body = response.body();
if (!body.equals("This is foo.txt\r\n")) {
- throw new RuntimeException();
+ throw new RuntimeException("Did not get expected body: "
+ + "\n\t expected \"This is foo.txt\\r\\n\""
+ + "\n\t received \""
+ + body.replace("\r", "\\r").replace("\n","\\n") + "\"");
}
// repeat async
HttpResponse<String> response1 = client.sendAsync(request, asString())
.join();
@@ -294,18 +296,17 @@
// POST use echo to check reply
static void test2a(String s) throws Exception {
System.out.print("test2a: " + s);
URI uri = new URI(s);
- Path p = Util.getTempFile(128 * 1024);
- //Path p = Util.getTempFile(1 * 1024);
+ Path p = getTempFile(128 * 1024);
HttpRequest request = HttpRequest.newBuilder(uri)
.POST(fromFile(p))
.build();
- Path resp = Util.getTempFile(1); // will be overwritten
+ Path resp = getTempFile(1); // will be overwritten
HttpResponse<Path> response =
client.send(request,
BodyHandler.asFile(resp,
StandardOpenOption.TRUNCATE_EXISTING,
@@ -313,10 +314,15 @@
if (response.statusCode() != 200) {
throw new RuntimeException(
"Expected 200, got [ " + response.statusCode() + " ]");
}
+ // no redirection, etc, should be no previous response
+ if (response.previousResponse().isPresent()) {
+ throw new RuntimeException(
+ "Unexpected previous response: " + response.previousResponse().get());
+ }
Path reply = response.body();
//System.out.println("Reply stored in " + reply.toString());
cmpFileContent(reply, p);
System.out.println(" OK");
}
@@ -345,11 +351,11 @@
Path downloaded = Paths.get("redir1.txt");
if (Files.size(downloaded) != Files.size(midSizedFile)) {
throw new RuntimeException("Size mismatch");
}
-
+ checkPreviousRedirectResponses(request, response);
System.out.printf(" (count: %d) ", handler.count());
// repeat with async api
handler.reset();
@@ -366,43 +372,114 @@
downloaded = Paths.get("redir2.txt");
if (Files.size(downloaded) != Files.size(midSizedFile)) {
throw new RuntimeException("Size mismatch 2");
}
+
+ checkPreviousRedirectResponses(request, response);
System.out.printf(" (count: %d) ", handler.count());
System.out.println(" OK");
}
+ static void checkPreviousRedirectResponses(HttpRequest initialRequest,
+ HttpResponse<?> finalResponse) {
+ // there must be at least one previous response
+ finalResponse.previousResponse()
+ .orElseThrow(() -> new RuntimeException("no previous response"));
+
+ HttpResponse<?> response = finalResponse;
+ do {
+ URI uri = response.uri();
+ response = response.previousResponse().get();
+ check(300 <= response.statusCode() && response.statusCode() <= 309,
+ "Expected 300 <= code <= 309, got:" + response.statusCode());
+ check(response.body() == null, "Unexpected body: " + response.body());
+ String locationHeader = response.headers().firstValue("Location")
+ .orElseThrow(() -> new RuntimeException("no previous Location"));
+ check(uri.toString().endsWith(locationHeader),
+ "URI: " + uri + ", Location: " + locationHeader);
+ } while (response.previousResponse().isPresent());
+
+ // initial
+ check(initialRequest.equals(response.request()),
+ "Expected initial request [%s] to equal last prev req [%s]",
+ initialRequest, response.request());
+ }
+
+ static void check(boolean cond, Object... msg) {
+ if (cond)
+ return;
+ StringBuilder sb = new StringBuilder();
+ for (Object o : msg)
+ sb.append(o);
+ throw new RuntimeException(sb.toString());
+ }
+
+ /**
+ * A Proxy Selector that wraps a ProxySelector.of(), and counts the number
+ * of times its select method has been invoked. This can be used to ensure
+ * that the Proxy Selector is invoked only once per HttpClient.sendXXX
+ * invocation.
+ */
+ static class CountingProxySelector extends ProxySelector {
+ private final ProxySelector proxySelector;
+ private volatile int count; // 0
+ private CountingProxySelector(InetSocketAddress proxyAddress) {
+ proxySelector = ProxySelector.of(proxyAddress);
+ }
+
+ public static CountingProxySelector of(InetSocketAddress proxyAddress) {
+ return new CountingProxySelector(proxyAddress);
+ }
+
+ int count() { return count; }
+
+ @Override
+ public List<Proxy> select(URI uri) {
+ count++;
+ return proxySelector.select(uri);
+ }
+
+ @Override
+ public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
+ proxySelector.connectFailed(uri, sa, ioe);
+ }
+ }
+
// Proxies
static void test4(String s) throws Exception {
System.out.print("test4: " + s);
URI uri = new URI(s);
InetSocketAddress proxyAddr = new InetSocketAddress("127.0.0.1", proxyPort);
String filename = fileroot + uri.getPath();
ExecutorService e = Executors.newCachedThreadPool();
+ CountingProxySelector ps = CountingProxySelector.of(proxyAddr);
HttpClient cl = HttpClient.newBuilder()
.executor(e)
- .proxy(ProxySelector.of(proxyAddr))
+ .proxy(ps)
.sslContext(ctx)
.sslParameters(sslparams)
.build();
HttpRequest request = HttpRequest.newBuilder(uri).GET().build();
- CompletableFuture<String> fut = client.sendAsync(request, asString())
+ CompletableFuture<String> fut = cl.sendAsync(request, asString())
.thenApply((response) -> response.body());
String body = fut.get(5, TimeUnit.HOURS);
String fc = getFileContent(filename);
if (!body.equals(fc)) {
throw new RuntimeException(
"Body mismatch: expected [" + body + "], got [" + fc + "]");
}
+ if (ps.count() != 1) {
+ throw new RuntimeException("CountingProxySelector. Expected 1, got " + ps.count());
+ }
e.shutdownNow();
System.out.println(" OK");
}
// 100 Continue: use echo target
@@ -463,11 +540,11 @@
}
@SuppressWarnings("rawtypes")
static void test7(String target) throws Exception {
System.out.print("test7: " + target);
- Path requestBody = Util.getTempFile(128 * 1024);
+ Path requestBody = getTempFile(128 * 1024);
// First test
URI uri = new URI(target);
HttpRequest request = HttpRequest.newBuilder().uri(uri).GET().build();
for (int i=0; i<4; i++) {
@@ -642,11 +719,11 @@
ConsoleHandler ch = new ConsoleHandler();
logger.setLevel(Level.SEVERE);
ch.setLevel(Level.SEVERE);
logger.addHandler(ch);
- String root = System.getProperty ("test.src")+ "/docs";
+ String root = System.getProperty ("test.src", ".")+ "/docs";
InetSocketAddress addr = new InetSocketAddress (0);
s1 = HttpServer.create (addr, 0);
if (s1 instanceof HttpsServer) {
throw new RuntimeException ("should not be httpsserver");
}
@@ -688,97 +765,21 @@
proxy = new ProxyServer(0, false);
proxyPort = proxy.getPort();
System.out.println("Proxy port = " + proxyPort);
}
-}
-
-class Configurator extends HttpsConfigurator {
- public Configurator(SSLContext ctx) {
- super(ctx);
- }
- public void configure (HttpsParameters params) {
- params.setSSLParameters (getSSLContext().getSupportedSSLParameters());
- }
-}
-
-class UploadServer extends Thread {
- int statusCode;
- ServerSocket ss;
- int port;
- int size;
- Object lock;
- boolean failed = false;
-
- UploadServer(int size) throws IOException {
- this.statusCode = statusCode;
- this.size = size;
- ss = new ServerSocket(0);
- port = ss.getLocalPort();
- lock = new Object();
- }
-
- int port() {
- return port;
- }
-
- int size() {
- return size;
- }
-
- // wait a sec before calling this
- boolean failed() {
- synchronized(lock) {
- return failed;
- }
- }
-
- @Override
- public void run () {
- int nbytes = 0;
- Socket s = null;
-
- synchronized(lock) {
- try {
- s = ss.accept();
-
- InputStream is = s.getInputStream();
- OutputStream os = s.getOutputStream();
- os.write("HTTP/1.1 201 OK\r\nContent-length: 0\r\n\r\n".getBytes());
- int n;
- byte[] buf = new byte[8000];
- while ((n=is.read(buf)) != -1) {
- nbytes += n;
- }
- } catch (IOException e) {
- System.out.println ("read " + nbytes);
- System.out.println ("size " + size);
- failed = nbytes >= size;
- } finally {
- try {
- ss.close();
- if (s != null)
- s.close();
- } catch (IOException e) {}
- }
- }
- }
-}
-
-class RedirectHandler implements HttpHandler {
- String root;
- volatile int count = 0;
+ static class RedirectHandler implements HttpHandler {
+ private final String root;
+ private volatile int count = 0;
RedirectHandler(String root) {
this.root = root;
}
@Override
- public synchronized void handle(HttpExchange t)
- throws IOException
- {
+ public synchronized void handle(HttpExchange t) throws IOException {
byte[] buf = new byte[2048];
try (InputStream is = t.getRequestBody()) {
while (is.read(buf) != -1) ;
}
@@ -787,26 +788,32 @@
if (count++ < 1) {
responseHeaders.add("Location", root + "/foo/" + count);
} else {
responseHeaders.add("Location", SmokeTest.midSizedFilename);
}
- t.sendResponseHeaders(301, -1);
+ t.sendResponseHeaders(301, 64 * 1024);
+ byte[] bb = new byte[1024];
+ OutputStream os = t.getResponseBody();
+ for (int i=0; i<64; i++) {
+ os.write(bb);
+ }
+ os.close();
t.close();
}
int count() {
return count;
}
void reset() {
count = 0;
}
-}
+ }
-class RedirectErrorHandler implements HttpHandler {
- String root;
- volatile int count = 1;
+ static class RedirectErrorHandler implements HttpHandler {
+ private final String root;
+ private volatile int count = 1;
RedirectErrorHandler(String root) {
this.root = root;
}
@@ -817,64 +824,25 @@
synchronized void increment() {
count++;
}
@Override
- public synchronized void handle (HttpExchange t)
- throws IOException
- {
- byte[] buf = new byte[2048];
+ public synchronized void handle(HttpExchange t) throws IOException {
try (InputStream is = t.getRequestBody()) {
- while (is.read(buf) != -1) ;
+ is.readAllBytes();
}
Headers map = t.getResponseHeaders();
String redirect = root + "/foo/" + Integer.toString(count);
increment();
map.add("Location", redirect);
t.sendResponseHeaders(301, -1);
t.close();
}
-}
-
-class Util {
- static byte[] readAll(InputStream is) throws IOException {
- byte[] buf = new byte[1024];
- byte[] result = new byte[0];
-
- while (true) {
- int n = is.read(buf);
- if (n > 0) {
- byte[] b1 = new byte[result.length + n];
- System.arraycopy(result, 0, b1, 0, result.length);
- System.arraycopy(buf, 0, b1, result.length, n);
- result = b1;
- } else if (n == -1) {
- return result;
- }
- }
- }
-
- static Path getTempFile(int size) throws IOException {
- File f = File.createTempFile("test", "txt");
- f.deleteOnExit();
- byte[] buf = new byte[2048];
- for (int i=0; i<buf.length; i++)
- buf[i] = (byte)i;
-
- FileOutputStream fos = new FileOutputStream(f);
- while (size > 0) {
- int amount = Math.min(size, buf.length);
- fos.write(buf, 0, amount);
- size -= amount;
- }
- fos.close();
- return f.toPath();
}
-}
-class DelayHandler implements HttpHandler {
+ static class DelayHandler implements HttpHandler {
CyclicBarrier bar1 = new CyclicBarrier(2);
CyclicBarrier bar2 = new CyclicBarrier(2);
CyclicBarrier bar3 = new CyclicBarrier(2);
@@ -886,19 +854,46 @@
return bar2;
}
@Override
public synchronized void handle(HttpExchange he) throws IOException {
- byte[] buf = Util.readAll(he.getRequestBody());
+ he.getRequestBody().readAllBytes();
try {
bar1.await();
bar2.await();
- } catch (Exception e) {}
+ } catch (Exception e) { }
he.sendResponseHeaders(200, -1); // will probably fail
he.close();
}
+ }
+ static class Configurator extends HttpsConfigurator {
+ public Configurator(SSLContext ctx) {
+ super(ctx);
+ }
+
+ public void configure (HttpsParameters params) {
+ params.setSSLParameters (getSSLContext().getSupportedSSLParameters());
+ }
+ }
+
+ static Path getTempFile(int size) throws IOException {
+ File f = File.createTempFile("test", "txt");
+ f.deleteOnExit();
+ byte[] buf = new byte[2048];
+ for (int i = 0; i < buf.length; i++)
+ buf[i] = (byte) i;
+
+ FileOutputStream fos = new FileOutputStream(f);
+ while (size > 0) {
+ int amount = Math.min(size, buf.length);
+ fos.write(buf, 0, amount);
+ size -= amount;
+ }
+ fos.close();
+ return f.toPath();
+ }
}
// check for simple hardcoded sequence and use remote address
// to check.
// First 4 requests executed in sequence (should use same connection/address)
< prev index next >