2de1b5ce26
Co-authored-by: Chris Hegarty <chris.hegarty@oracle.com> Co-authored-by: Daniel Fuchs <daniel.fuchs@oracle.com> Co-authored-by: Pavel Rappo <pavel.rappo@oracle.com> Co-authored-by: Sergey Kuksenko <sergey.kuksenko@oracle.com> Co-authored-by: Anthony Vanelverdinghe <anthony.vanelverdinghe@gmail.com> Reviewed-by: chegar, dfuchs, michaelm, prappo, skuksenko
303 lines
11 KiB
Java
303 lines
11 KiB
Java
/*
|
|
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
/*
|
|
* @test @bug 8087112
|
|
* @modules jdk.incubator.httpclient
|
|
* java.logging
|
|
* jdk.httpserver
|
|
* @library /lib/testlibrary/
|
|
* @compile ../../../com/sun/net/httpserver/LogFilter.java
|
|
* @compile ../../../com/sun/net/httpserver/FileServerHandler.java
|
|
* @build LightWeightHttpServer
|
|
* @build jdk.testlibrary.SimpleSSLContext
|
|
* @run testng/othervm RequestBodyTest
|
|
*/
|
|
|
|
import java.io.*;
|
|
import java.net.URI;
|
|
import jdk.incubator.http.HttpClient;
|
|
import jdk.incubator.http.HttpRequest;
|
|
import jdk.incubator.http.HttpResponse;
|
|
import java.nio.charset.Charset;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.Paths;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
import java.util.Optional;
|
|
import java.util.concurrent.ExecutorService;
|
|
import java.util.concurrent.Executors;
|
|
import java.util.function.Supplier;
|
|
import javax.net.ssl.SSLContext;
|
|
import jdk.testlibrary.FileUtils;
|
|
import static java.nio.charset.StandardCharsets.*;
|
|
import static java.nio.file.StandardOpenOption.*;
|
|
import static jdk.incubator.http.HttpRequest.BodyProcessor.*;
|
|
import static jdk.incubator.http.HttpResponse.BodyHandler.*;
|
|
|
|
import org.testng.annotations.AfterTest;
|
|
import org.testng.annotations.BeforeTest;
|
|
import org.testng.annotations.DataProvider;
|
|
import org.testng.annotations.Test;
|
|
import static org.testng.Assert.*;
|
|
|
|
public class RequestBodyTest {
|
|
|
|
static final String fileroot = System.getProperty("test.src") + "/docs";
|
|
static final String midSizedFilename = "/files/notsobigfile.txt";
|
|
static final String smallFilename = "/files/smallfile.txt";
|
|
|
|
HttpClient client;
|
|
ExecutorService exec = Executors.newCachedThreadPool();
|
|
String httpURI;
|
|
String httpsURI;
|
|
|
|
enum RequestBody {
|
|
BYTE_ARRAY,
|
|
BYTE_ARRAY_OFFSET,
|
|
BYTE_ARRAYS,
|
|
FILE,
|
|
INPUTSTREAM,
|
|
STRING,
|
|
STRING_WITH_CHARSET
|
|
}
|
|
|
|
enum ResponseBody {
|
|
BYTE_ARRAY,
|
|
BYTE_ARRAY_CONSUMER,
|
|
DISCARD,
|
|
FILE,
|
|
FILE_WITH_OPTION,
|
|
STRING,
|
|
STRING_WITH_CHARSET,
|
|
}
|
|
|
|
@BeforeTest
|
|
public void setup() throws Exception {
|
|
LightWeightHttpServer.initServer();
|
|
httpURI = LightWeightHttpServer.httproot + "echo/foo";
|
|
httpsURI = LightWeightHttpServer.httpsroot + "echo/foo";
|
|
|
|
SSLContext ctx = LightWeightHttpServer.ctx;
|
|
client = HttpClient.newBuilder()
|
|
.sslContext(ctx)
|
|
.followRedirects(HttpClient.Redirect.ALWAYS)
|
|
.executor(exec)
|
|
.build();
|
|
}
|
|
|
|
@AfterTest
|
|
public void teardown() throws Exception {
|
|
exec.shutdownNow();
|
|
LightWeightHttpServer.stop();
|
|
}
|
|
|
|
@DataProvider
|
|
public Object[][] exchanges() throws Exception {
|
|
List<Object[]> values = new ArrayList<>();
|
|
|
|
for (boolean async : new boolean[] { false, true })
|
|
for (String uri : new String[] { httpURI, httpsURI })
|
|
for (String file : new String[] { smallFilename, midSizedFilename })
|
|
for (RequestBody requestBodyType : RequestBody.values())
|
|
for (ResponseBody responseBodyType : ResponseBody.values())
|
|
values.add(new Object[]
|
|
{uri, requestBodyType, responseBodyType, file, async});
|
|
|
|
return values.stream().toArray(Object[][]::new);
|
|
}
|
|
|
|
@Test(dataProvider = "exchanges")
|
|
void exchange(String target,
|
|
RequestBody requestBodyType,
|
|
ResponseBody responseBodyType,
|
|
String file,
|
|
boolean async)
|
|
throws Exception
|
|
{
|
|
Path filePath = Paths.get(fileroot + file);
|
|
URI uri = new URI(target);
|
|
|
|
HttpRequest request = createRequest(uri, requestBodyType, filePath);
|
|
|
|
checkResponse(client, request, requestBodyType, responseBodyType, filePath, async);
|
|
}
|
|
|
|
static final int DEFAULT_OFFSET = 10;
|
|
static final int DEFAULT_LENGTH = 1000;
|
|
|
|
HttpRequest createRequest(URI uri,
|
|
RequestBody requestBodyType,
|
|
Path file)
|
|
throws IOException
|
|
{
|
|
HttpRequest.Builder rb = HttpRequest.newBuilder(uri);
|
|
|
|
String filename = file.toFile().getAbsolutePath();
|
|
byte[] fileAsBytes = getFileBytes(filename);
|
|
String fileAsString = new String(fileAsBytes, UTF_8);
|
|
|
|
switch (requestBodyType) {
|
|
case BYTE_ARRAY:
|
|
rb.POST(fromByteArray(fileAsBytes));
|
|
break;
|
|
case BYTE_ARRAY_OFFSET:
|
|
rb.POST(fromByteArray(fileAsBytes, DEFAULT_OFFSET, DEFAULT_LENGTH));
|
|
break;
|
|
case BYTE_ARRAYS:
|
|
Iterable<byte[]> iterable = Arrays.asList(fileAsBytes);
|
|
rb.POST(fromByteArrays(iterable));
|
|
break;
|
|
case FILE:
|
|
rb.POST(fromFile(file));
|
|
break;
|
|
case INPUTSTREAM:
|
|
rb.POST(fromInputStream(fileInputStreamSupplier(file)));
|
|
break;
|
|
case STRING:
|
|
rb.POST(fromString(fileAsString));
|
|
break;
|
|
case STRING_WITH_CHARSET:
|
|
rb.POST(fromString(new String(fileAsBytes), Charset.defaultCharset()));
|
|
break;
|
|
default:
|
|
throw new AssertionError("Unknown request body:" + requestBodyType);
|
|
}
|
|
return rb.build();
|
|
}
|
|
|
|
void checkResponse(HttpClient client,
|
|
HttpRequest request,
|
|
RequestBody requestBodyType,
|
|
ResponseBody responseBodyType,
|
|
Path file,
|
|
boolean async)
|
|
throws InterruptedException, IOException
|
|
{
|
|
String filename = file.toFile().getAbsolutePath();
|
|
byte[] fileAsBytes = getFileBytes(filename);
|
|
if (requestBodyType == RequestBody.BYTE_ARRAY_OFFSET) {
|
|
// Truncate the expected response body, if only a portion was sent
|
|
fileAsBytes = Arrays.copyOfRange(fileAsBytes,
|
|
DEFAULT_OFFSET,
|
|
DEFAULT_OFFSET + DEFAULT_LENGTH);
|
|
}
|
|
String fileAsString = new String(fileAsBytes, UTF_8);
|
|
Path tempFile = Paths.get("RequestBodyTest.tmp");
|
|
FileUtils.deleteFileIfExistsWithRetry(tempFile);
|
|
|
|
switch (responseBodyType) {
|
|
case BYTE_ARRAY:
|
|
HttpResponse<byte[]> bar = getResponse(client, request, asByteArray(), async);
|
|
assertEquals(bar.statusCode(), 200);
|
|
assertEquals(bar.body(), fileAsBytes);
|
|
break;
|
|
case BYTE_ARRAY_CONSUMER:
|
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
HttpResponse<Void> v = getResponse(client, request,
|
|
asByteArrayConsumer(o -> consumerBytes(o, baos) ), async);
|
|
byte[] ba = baos.toByteArray();
|
|
assertEquals(v.statusCode(), 200);
|
|
assertEquals(ba, fileAsBytes);
|
|
break;
|
|
case DISCARD:
|
|
Object o = new Object();
|
|
HttpResponse<Object> or = getResponse(client, request, discard(o), async);
|
|
assertEquals(or.statusCode(), 200);
|
|
assertSame(or.body(), o);
|
|
break;
|
|
case FILE:
|
|
HttpResponse<Path> fr = getResponse(client, request, asFile(tempFile), async);
|
|
assertEquals(fr.statusCode(), 200);
|
|
assertEquals(Files.size(tempFile), fileAsString.length());
|
|
assertEquals(Files.readAllBytes(tempFile), fileAsBytes);
|
|
break;
|
|
case FILE_WITH_OPTION:
|
|
fr = getResponse(client, request, asFile(tempFile, CREATE_NEW, WRITE), async);
|
|
assertEquals(fr.statusCode(), 200);
|
|
assertEquals(Files.size(tempFile), fileAsString.length());
|
|
assertEquals(Files.readAllBytes(tempFile), fileAsBytes);
|
|
break;
|
|
case STRING:
|
|
HttpResponse<String> sr = getResponse(client, request, asString(), async);
|
|
assertEquals(sr.statusCode(), 200);
|
|
assertEquals(sr.body(), fileAsString);
|
|
break;
|
|
case STRING_WITH_CHARSET:
|
|
HttpResponse<String> r = getResponse(client, request, asString(StandardCharsets.UTF_8), async);
|
|
assertEquals(r.statusCode(), 200);
|
|
assertEquals(r.body(), fileAsString);
|
|
break;
|
|
default:
|
|
throw new AssertionError("Unknown response body:" + responseBodyType);
|
|
}
|
|
}
|
|
|
|
static <T> HttpResponse<T> getResponse(HttpClient client,
|
|
HttpRequest request,
|
|
HttpResponse.BodyHandler<T> handler,
|
|
boolean async)
|
|
throws InterruptedException, IOException
|
|
{
|
|
if (!async)
|
|
return client.send(request, handler);
|
|
else
|
|
return client.sendAsync(request, handler).join();
|
|
}
|
|
|
|
static byte[] getFileBytes(String path) throws IOException {
|
|
try (FileInputStream fis = new FileInputStream(path);
|
|
BufferedInputStream bis = new BufferedInputStream(fis);
|
|
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
|
bis.transferTo(baos);
|
|
return baos.toByteArray();
|
|
}
|
|
}
|
|
|
|
static Supplier<FileInputStream> fileInputStreamSupplier(Path f) {
|
|
return new Supplier<>() {
|
|
Path file = f;
|
|
@Override
|
|
public FileInputStream get() {
|
|
try {
|
|
return new FileInputStream(file.toFile());
|
|
} catch (FileNotFoundException x) {
|
|
throw new UncheckedIOException(x);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
static void consumerBytes(Optional<byte[]> bytes, ByteArrayOutputStream baos) {
|
|
try {
|
|
if (bytes.isPresent())
|
|
baos.write(bytes.get());
|
|
} catch (IOException x) {
|
|
throw new UncheckedIOException(x);
|
|
}
|
|
}
|
|
}
|