SslHandler factory, switch to JUnit 5
This commit is contained in:
parent
ad460a5111
commit
ef0c59d3f5
76 changed files with 2041 additions and 678 deletions
29
build.gradle
29
build.gradle
|
@ -37,6 +37,9 @@ subprojects {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-api:${project.property('junit.version')}"
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-params:${project.property('junit.version')}"
|
||||
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${project.property('junit.version')}"
|
||||
alpnagent "org.mortbay.jetty.alpn:jetty-alpn-agent:${project.property('alpnagent.version')}"
|
||||
asciidoclet "org.asciidoctor:asciidoclet:${project.property('asciidoclet.version')}"
|
||||
wagon "org.apache.maven.wagon:wagon-ssh:${project.property('wagon.version')}"
|
||||
|
@ -52,9 +55,11 @@ subprojects {
|
|||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
|
||||
tasks.withType(JavaCompile) {
|
||||
options.compilerArgs << "-Xlint:all,-serial"
|
||||
options.compilerArgs << "-Xlint:all,-fallthrough"
|
||||
if (!options.compilerArgs.contains("-processor")) {
|
||||
options.compilerArgs << '-proc:none'
|
||||
}
|
||||
}
|
||||
|
||||
jar {
|
||||
|
@ -64,10 +69,20 @@ subprojects {
|
|||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
systemProperty 'java.util.logging.config.file', 'src/test/resources/logging.properties'
|
||||
failFast = false
|
||||
testLogging {
|
||||
showStandardStreams = false
|
||||
exceptionFormat = 'full'
|
||||
events 'PASSED', 'FAILED', 'SKIPPED'
|
||||
}
|
||||
afterSuite { desc, result ->
|
||||
if (!desc.parent) {
|
||||
println "\nTest result: ${result.resultType}"
|
||||
println "Test summary: ${result.testCount} tests, " +
|
||||
"${result.successfulTestCount} succeeded, " +
|
||||
"${result.failedTestCount} failed, " +
|
||||
"${result.skippedTestCount} skipped"
|
||||
}
|
||||
}
|
||||
if (JavaVersion.current() == JavaVersion.VERSION_1_8) {
|
||||
jvmArgs "-javaagent:" + configurations.alpnagent.asPath
|
||||
|
@ -105,13 +120,13 @@ subprojects {
|
|||
task javadocJar(type: Jar, dependsOn: classes) {
|
||||
from javadoc
|
||||
into "build/tmp"
|
||||
classifier 'javadoc'
|
||||
archiveClassifier.set('javadoc')
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar, dependsOn: classes) {
|
||||
from sourceSets.main.allSource
|
||||
into "build/tmp"
|
||||
classifier 'sources'
|
||||
archiveClassifier.set('sources')
|
||||
}
|
||||
|
||||
artifacts {
|
||||
|
@ -202,7 +217,7 @@ subprojects {
|
|||
}
|
||||
|
||||
spotbugs {
|
||||
toolVersion = '3.1.3'
|
||||
toolVersion = '3.1.12'
|
||||
sourceSets = [sourceSets.main]
|
||||
ignoreFailures = true
|
||||
effort = "max"
|
||||
|
|
|
@ -1,16 +1,24 @@
|
|||
group = org.xbib
|
||||
name = netty-http
|
||||
version = 4.1.35.0
|
||||
version = 4.1.35.1
|
||||
|
||||
# main packages
|
||||
netty.version = 4.1.35.Final
|
||||
tcnative.version = 2.0.22.Final
|
||||
bouncycastle.version = 1.61
|
||||
alpnagent.version = 2.0.9
|
||||
|
||||
# common
|
||||
xbib-net-url.version = 1.2.2
|
||||
|
||||
# server
|
||||
bouncycastle.version = 1.61
|
||||
|
||||
# server-rest
|
||||
xbib-guice.version = 4.0.4
|
||||
|
||||
|
||||
# test packages
|
||||
junit.version = 4.12
|
||||
junit.version = 5.4.2
|
||||
conscrypt.version = 2.0.0
|
||||
jackson.version = 2.8.11.1
|
||||
wagon.version = 3.0.0
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
|
||||
dependencies {
|
||||
compile project(":netty-http-common")
|
||||
compile "io.netty:netty-handler-proxy:${project.property('netty.version')}"
|
||||
compile "io.netty:netty-transport-native-epoll:${project.property('netty.version')}"
|
||||
implementation project(":netty-http-common")
|
||||
implementation "io.netty:netty-handler-proxy:${project.property('netty.version')}"
|
||||
implementation "io.netty:netty-transport-native-epoll:${project.property('netty.version')}"
|
||||
implementation "io.netty:netty-codec-http2:${project.property('netty.version')}"
|
||||
implementation "org.xbib:net-url:${project.property('xbib-net-url.version')}"
|
||||
|
||||
testCompile "io.netty:netty-tcnative-boringssl-static:${project.property('tcnative.version')}"
|
||||
testCompile "org.conscrypt:conscrypt-openjdk-uber:${project.property('conscrypt.version')}"
|
||||
testCompile "junit:junit:${project.property('junit.version')}"
|
||||
testCompile "com.fasterxml.jackson.core:jackson-databind:${project.property('jackson.version')}"
|
||||
testImplementation "io.netty:netty-tcnative-boringssl-static:${project.property('tcnative.version')}"
|
||||
testImplementation "org.conscrypt:conscrypt-openjdk-uber:${project.property('conscrypt.version')}"
|
||||
testImplementation "com.fasterxml.jackson.core:jackson-databind:${project.property('jackson.version')}"
|
||||
}
|
||||
|
|
|
@ -199,13 +199,13 @@ public final class Client {
|
|||
Channel channel;
|
||||
if (httpAddress != null) {
|
||||
HttpVersion httpVersion = httpAddress.getVersion();
|
||||
SslHandlerFactory sslHandlerFactory = new SslHandlerFactory(clientConfig, httpAddress, byteBufAllocator);
|
||||
ChannelInitializer<Channel> initializer;
|
||||
SslHandler sslHandler = newSslHandler(clientConfig, byteBufAllocator, httpAddress);
|
||||
if (httpVersion.majorVersion() == 1) {
|
||||
initializer = new HttpChannelInitializer(clientConfig, httpAddress, sslHandler,
|
||||
new Http2ChannelInitializer(clientConfig, httpAddress, sslHandler));
|
||||
initializer = new HttpChannelInitializer(clientConfig, httpAddress, sslHandlerFactory,
|
||||
new Http2ChannelInitializer(clientConfig, httpAddress, sslHandlerFactory));
|
||||
} else {
|
||||
initializer = new Http2ChannelInitializer(clientConfig, httpAddress, sslHandler);
|
||||
initializer = new Http2ChannelInitializer(clientConfig, httpAddress, sslHandlerFactory);
|
||||
}
|
||||
try {
|
||||
channel = bootstrap.handler(initializer)
|
||||
|
@ -412,15 +412,34 @@ public final class Client {
|
|||
public void channelCreated(Channel channel) {
|
||||
HttpAddress httpAddress = channel.attr(pool.getAttributeKey()).get();
|
||||
HttpVersion httpVersion = httpAddress.getVersion();
|
||||
SslHandler sslHandler = newSslHandler(clientConfig, byteBufAllocator, httpAddress);
|
||||
SslHandlerFactory sslHandlerFactory = new SslHandlerFactory(clientConfig, httpAddress, byteBufAllocator);
|
||||
Http2ChannelInitializer http2ChannelInitializer = new Http2ChannelInitializer(clientConfig, httpAddress, sslHandlerFactory);
|
||||
if (httpVersion.majorVersion() == 1) {
|
||||
HttpChannelInitializer initializer = new HttpChannelInitializer(clientConfig, httpAddress, sslHandler,
|
||||
new Http2ChannelInitializer(clientConfig, httpAddress, sslHandler));
|
||||
HttpChannelInitializer initializer = new HttpChannelInitializer(clientConfig, httpAddress, sslHandlerFactory,
|
||||
http2ChannelInitializer);
|
||||
initializer.initChannel(channel);
|
||||
} else {
|
||||
Http2ChannelInitializer initializer = new Http2ChannelInitializer(clientConfig, httpAddress, sslHandler);
|
||||
initializer.initChannel(channel);
|
||||
http2ChannelInitializer.initChannel(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SslHandlerFactory {
|
||||
|
||||
private final ClientConfig clientConfig;
|
||||
|
||||
private final HttpAddress httpAddress;
|
||||
|
||||
private final ByteBufAllocator allocator;
|
||||
|
||||
SslHandlerFactory(ClientConfig clientConfig, HttpAddress httpAddress, ByteBufAllocator allocator) {
|
||||
this.clientConfig = clientConfig;
|
||||
this.httpAddress = httpAddress;
|
||||
this.allocator = allocator;
|
||||
}
|
||||
|
||||
public SslHandler create() {
|
||||
return newSslHandler(clientConfig, allocator, httpAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import io.netty.handler.codec.http.HttpObjectAggregator;
|
|||
import io.netty.handler.logging.LogLevel;
|
||||
import io.netty.handler.ssl.ApplicationProtocolNames;
|
||||
import io.netty.handler.ssl.ApplicationProtocolNegotiationHandler;
|
||||
import io.netty.handler.ssl.SslHandler;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
import org.xbib.netty.http.client.ClientConfig;
|
||||
import org.xbib.netty.http.client.handler.http2.Http2ChannelInitializer;
|
||||
import org.xbib.netty.http.common.HttpAddress;
|
||||
|
@ -26,7 +26,7 @@ public class HttpChannelInitializer extends ChannelInitializer<Channel> {
|
|||
|
||||
private final HttpAddress httpAddress;
|
||||
|
||||
private final SslHandler sslHandler;
|
||||
private final Client.SslHandlerFactory sslHandlerFactory;
|
||||
|
||||
private final HttpResponseHandler httpResponseHandler;
|
||||
|
||||
|
@ -34,11 +34,11 @@ public class HttpChannelInitializer extends ChannelInitializer<Channel> {
|
|||
|
||||
public HttpChannelInitializer(ClientConfig clientConfig,
|
||||
HttpAddress httpAddress,
|
||||
SslHandler sslHandler,
|
||||
Client.SslHandlerFactory sslHandlerFactory,
|
||||
Http2ChannelInitializer http2ChannelInitializer) {
|
||||
this.clientConfig = clientConfig;
|
||||
this.httpAddress = httpAddress;
|
||||
this.sslHandler = sslHandler;
|
||||
this.sslHandlerFactory = sslHandlerFactory;
|
||||
this.http2ChannelInitializer = http2ChannelInitializer;
|
||||
this.httpResponseHandler = new HttpResponseHandler();
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ public class HttpChannelInitializer extends ChannelInitializer<Channel> {
|
|||
|
||||
private void configureEncrypted(Channel channel) {
|
||||
ChannelPipeline pipeline = channel.pipeline();
|
||||
pipeline.addLast(sslHandler);
|
||||
pipeline.addLast(sslHandlerFactory.create());
|
||||
if (clientConfig.isEnableNegotiation()) {
|
||||
ApplicationProtocolNegotiationHandler negotiationHandler =
|
||||
new ApplicationProtocolNegotiationHandler(ApplicationProtocolNames.HTTP_1_1) {
|
||||
|
@ -101,10 +101,6 @@ public class HttpChannelInitializer extends ChannelInitializer<Channel> {
|
|||
false);
|
||||
httpObjectAggregator.setMaxCumulationBufferComponents(clientConfig.getMaxCompositeBufferComponents());
|
||||
pipeline.addLast(httpObjectAggregator);
|
||||
/*if (clientConfig.isEnableGzip()) {
|
||||
pipeline.addLast(new HttpChunkContentCompressor(6));
|
||||
}
|
||||
pipeline.addLast(new ChunkedWriteHandler());*/
|
||||
pipeline.addLast(httpResponseHandler);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import io.netty.handler.codec.http2.Http2Headers;
|
|||
import io.netty.handler.codec.http2.Http2MultiplexCodec;
|
||||
import io.netty.handler.codec.http2.Http2MultiplexCodecBuilder;
|
||||
import io.netty.handler.logging.LogLevel;
|
||||
import io.netty.handler.ssl.SslHandler;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
import org.xbib.netty.http.client.ClientConfig;
|
||||
import org.xbib.netty.http.client.handler.http.TrafficLoggingHandler;
|
||||
import org.xbib.netty.http.client.transport.Transport;
|
||||
|
@ -29,14 +29,14 @@ public class Http2ChannelInitializer extends ChannelInitializer<Channel> {
|
|||
|
||||
private final HttpAddress httpAddress;
|
||||
|
||||
private final SslHandler sslHandler;
|
||||
private final Client.SslHandlerFactory sslHandlerFactory;
|
||||
|
||||
public Http2ChannelInitializer(ClientConfig clientConfig,
|
||||
HttpAddress httpAddress,
|
||||
SslHandler sslHandler) {
|
||||
Client.SslHandlerFactory sslHandlerFactory) {
|
||||
this.clientConfig = clientConfig;
|
||||
this.httpAddress = httpAddress;
|
||||
this.sslHandler = sslHandler;
|
||||
this.sslHandlerFactory = sslHandlerFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -55,7 +55,7 @@ public class Http2ChannelInitializer extends ChannelInitializer<Channel> {
|
|||
}
|
||||
|
||||
private void configureEncrypted(Channel channel) {
|
||||
channel.pipeline().addLast(sslHandler);
|
||||
channel.pipeline().addLast(sslHandlerFactory.create());
|
||||
configureCleartext(channel);
|
||||
}
|
||||
|
||||
|
|
|
@ -80,12 +80,8 @@ public class HttpTransport extends BaseTransport {
|
|||
logger.log(Level.WARNING, "throwable not null for response " + fullHttpResponse, throwable);
|
||||
return;
|
||||
}
|
||||
if (requests.isEmpty()) {
|
||||
logger.log(Level.WARNING, "no request present, can not handle response " + fullHttpResponse);
|
||||
return;
|
||||
}
|
||||
// streamID is expected to be null, last request on memory is expected to be current, remove request from memory
|
||||
Request request = requests.remove(requests.lastKey());
|
||||
Request request = requests.remove(requests.isEmpty() ? null : requests.lastKey());
|
||||
if (request != null) {
|
||||
for (String cookieString : fullHttpResponse.headers().getAll(HttpHeaderNames.SET_COOKIE)) {
|
||||
Cookie cookie = ClientCookieDecoder.STRICT.decode(cookieString);
|
||||
|
@ -140,6 +136,6 @@ public class HttpTransport extends BaseTransport {
|
|||
|
||||
@Override
|
||||
protected String getRequestKey(String channelId, Integer streamId) {
|
||||
return requests.lastKey();
|
||||
return requests.isEmpty() ? null : requests.lastKey();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package org.xbib.netty.http.client.test;
|
||||
|
||||
import io.netty.handler.codec.http.FullHttpResponse;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
import org.xbib.netty.http.client.Request;
|
||||
|
||||
|
@ -12,7 +12,7 @@ import java.util.function.Function;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class CompletableFutureTest {
|
||||
class CompletableFutureTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CompletableFutureTest.class.getName());
|
||||
|
||||
|
@ -20,7 +20,7 @@ public class CompletableFutureTest {
|
|||
* Get some weird content from one URL and post it to another URL, by composing completable futures.
|
||||
*/
|
||||
@Test
|
||||
public void testComposeCompletableFutures() throws IOException {
|
||||
void testComposeCompletableFutures() throws IOException {
|
||||
Client client = Client.builder().build();
|
||||
try {
|
||||
final Function<FullHttpResponse, String> httpResponseStringFunction = response ->
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package org.xbib.netty.http.client.test;
|
||||
|
||||
import org.conscrypt.Conscrypt;
|
||||
import org.junit.Test;
|
||||
import org.xbib.TestBase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
import org.xbib.netty.http.client.Request;
|
||||
|
||||
|
@ -11,14 +11,14 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class ConscryptTest extends TestBase {
|
||||
@ExtendWith(NettyHttpExtension.class)
|
||||
class ConscryptTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger("");
|
||||
private static final Logger logger = Logger.getLogger(ConscryptTest.class.getName());
|
||||
|
||||
@Test
|
||||
public void testConscrypt() throws IOException {
|
||||
void testConscrypt() throws IOException {
|
||||
Client client = Client.builder()
|
||||
.enableDebug()
|
||||
.setJdkSslProvider()
|
||||
.setSslContextProvider(Conscrypt.newProvider())
|
||||
.build();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package org.xbib.netty.http.client.test;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.xbib.TestBase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
import org.xbib.netty.http.client.Request;
|
||||
|
||||
|
@ -10,9 +10,8 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class CookieSetterHttpBinTest extends TestBase {
|
||||
@ExtendWith(NettyHttpExtension.class)
|
||||
class CookieSetterHttpBinTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CookieSetterHttpBinTest.class.getName());
|
||||
|
||||
|
@ -30,7 +29,7 @@ public class CookieSetterHttpBinTest extends TestBase {
|
|||
* @throws IOException if test fails
|
||||
*/
|
||||
@Test
|
||||
public void testHttpBinCookies() throws IOException {
|
||||
void testHttpBinCookies() throws IOException {
|
||||
Client client = new Client();
|
||||
try {
|
||||
Request request = Request.get()
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package org.xbib.netty.http.client.test;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.xbib.TestBase;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
import org.xbib.netty.http.common.HttpAddress;
|
||||
import org.xbib.netty.http.client.Request;
|
||||
|
@ -18,17 +18,18 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@Ignore
|
||||
public class ElasticsearchTest extends TestBase {
|
||||
@Disabled
|
||||
@ExtendWith(NettyHttpExtension.class)
|
||||
class ElasticsearchTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ElasticsearchTest.class.getName());
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testElasticsearch() throws IOException {
|
||||
Client client = Client.builder().enableDebug().build();
|
||||
void testElasticsearch() throws IOException {
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
try {
|
||||
Request request = Request.get().url("http://localhost:9200")
|
||||
.build()
|
||||
|
@ -44,9 +45,9 @@ public class ElasticsearchTest extends TestBase {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testElasticsearchCreateDocument() throws IOException {
|
||||
Client client = Client.builder().enableDebug().build();
|
||||
void testElasticsearchCreateDocument() throws IOException {
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
try {
|
||||
Request request = Request.put().url("http://localhost:9200/test/test/1")
|
||||
.json("{\"text\":\"Hello World\"}")
|
||||
|
@ -63,8 +64,7 @@ public class ElasticsearchTest extends TestBase {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testElasticsearchMatchQuery() throws IOException {
|
||||
void testElasticsearchMatchQuery() throws IOException {
|
||||
Client client = new Client();
|
||||
try {
|
||||
Request request = Request.post().url("http://localhost:9200/test/_search")
|
||||
|
@ -85,7 +85,7 @@ public class ElasticsearchTest extends TestBase {
|
|||
* @throws IOException if test fails
|
||||
*/
|
||||
@Test
|
||||
public void testElasticsearchPooled() throws IOException {
|
||||
void testElasticsearchPooled() throws IOException {
|
||||
HttpAddress httpAddress = HttpAddress.http1("localhost", 9200);
|
||||
int limit = 4;
|
||||
Client client = Client.builder()
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package org.xbib.netty.http.client.test;
|
||||
|
||||
import io.netty.handler.codec.http.HttpMethod;
|
||||
import org.junit.Test;
|
||||
import org.xbib.TestBase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
import org.xbib.netty.http.client.Request;
|
||||
|
||||
|
@ -11,13 +11,15 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class Http1Test extends TestBase {
|
||||
@ExtendWith(NettyHttpExtension.class)
|
||||
class Http1Test {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(Http1Test.class.getName());
|
||||
|
||||
@Test
|
||||
public void testHttp1() throws Exception {
|
||||
Client client = Client.builder().enableDebug().build();
|
||||
void testHttp1() throws Exception {
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
try {
|
||||
Request request = Request.get().url("http://xbib.org").build()
|
||||
.setResponseListener(msg -> logger.log(Level.INFO, "got response: " +
|
||||
|
@ -31,8 +33,28 @@ public class Http1Test extends TestBase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testParallelRequests() throws IOException {
|
||||
Client client = Client.builder().enableDebug().build();
|
||||
void testSequentialRequests() throws Exception {
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
try {
|
||||
Request request1 = Request.get().url("http://xbib.org").build()
|
||||
.setResponseListener(msg -> logger.log(Level.INFO, "got response: " +
|
||||
msg.content().toString(StandardCharsets.UTF_8)));
|
||||
client.execute(request1).get();
|
||||
|
||||
Request request2 = Request.get().url("http://google.com").setVersion("HTTP/1.1").build()
|
||||
.setResponseListener(msg -> logger.log(Level.INFO, "got response: " +
|
||||
msg.content().toString(StandardCharsets.UTF_8)));
|
||||
client.execute(request2).get();
|
||||
} finally {
|
||||
client.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParallelRequests() throws IOException {
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
try {
|
||||
Request request1 = Request.builder(HttpMethod.GET)
|
||||
.url("http://xbib.org").setVersion("HTTP/1.1")
|
||||
|
@ -58,22 +80,4 @@ public class Http1Test extends TestBase {
|
|||
client.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSequentialRequests() throws Exception {
|
||||
Client client = Client.builder().enableDebug().build();
|
||||
try {
|
||||
Request request1 = Request.get().url("http://xbib.org").build()
|
||||
.setResponseListener(msg -> logger.log(Level.INFO, "got response: " +
|
||||
msg.content().toString(StandardCharsets.UTF_8)));
|
||||
client.execute(request1).get();
|
||||
|
||||
Request request2 = Request.get().url("http://google.com").setVersion("HTTP/1.1").build()
|
||||
.setResponseListener(msg -> logger.log(Level.INFO, "got response: " +
|
||||
msg.content().toString(StandardCharsets.UTF_8)));
|
||||
client.execute(request2).get();
|
||||
} finally {
|
||||
client.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package org.xbib.netty.http.client.test;
|
||||
|
||||
import io.netty.handler.codec.http.HttpMethod;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.xbib.TestBase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
import org.xbib.netty.http.client.Request;
|
||||
|
||||
|
@ -12,7 +11,8 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class Http2Test extends TestBase {
|
||||
@ExtendWith(NettyHttpExtension.class)
|
||||
class Http2Test {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(Http2Test.class.getName());
|
||||
|
||||
|
@ -29,10 +29,8 @@ public class Http2Test extends TestBase {
|
|||
* @throws IOException if test fails
|
||||
*/
|
||||
@Test
|
||||
@Ignore
|
||||
public void testAkamai() throws IOException {
|
||||
void testAkamai() throws IOException {
|
||||
Client client = Client.builder()
|
||||
.enableDebug()
|
||||
.addServerNameForIdentification("http2.akamai.com")
|
||||
.build();
|
||||
try {
|
||||
|
@ -53,8 +51,9 @@ public class Http2Test extends TestBase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testWebtide() throws Exception {
|
||||
Client client = Client.builder().enableDebug().build();
|
||||
void testWebtide() throws Exception {
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
client.logDiagnostics(Level.INFO);
|
||||
try {
|
||||
Request request = Request.get().url("https://webtide.com").setVersion("HTTP/2.0").build()
|
||||
|
@ -69,10 +68,9 @@ public class Http2Test extends TestBase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testHttp2PushIO() throws IOException {
|
||||
void testHttp2PushIO() throws IOException {
|
||||
String url = "https://http2-push.io";
|
||||
Client client = Client.builder()
|
||||
.enableDebug()
|
||||
.addServerNameForIdentification("http2-push.io")
|
||||
.build();
|
||||
try {
|
||||
|
@ -91,7 +89,7 @@ public class Http2Test extends TestBase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testWebtideTwoRequestsOnSameConnection() throws IOException {
|
||||
void testWebtideTwoRequestsOnSameConnection() throws IOException {
|
||||
Client client = new Client();
|
||||
try {
|
||||
Request request1 = Request.builder(HttpMethod.GET)
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
package org.xbib.netty.http.server.test;
|
||||
package org.xbib.netty.http.client.test;
|
||||
|
||||
import org.junit.jupiter.api.extension.BeforeAllCallback;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
|
||||
import java.util.logging.ConsoleHandler;
|
||||
import java.util.logging.Handler;
|
||||
|
@ -7,10 +10,10 @@ import java.util.logging.LogManager;
|
|||
import java.util.logging.Logger;
|
||||
import java.util.logging.SimpleFormatter;
|
||||
|
||||
public class TestBase {
|
||||
|
||||
static {
|
||||
public class NettyHttpExtension implements BeforeAllCallback {
|
||||
|
||||
@Override
|
||||
public void beforeAll(ExtensionContext context) throws Exception {
|
||||
System.setProperty("io.netty.noUnsafe", Boolean.toString(true));
|
||||
System.setProperty("io.netty.noKeySetOptimization", Boolean.toString(true));
|
||||
//System.setProperty("io.netty.recycler.maxCapacity", Integer.toString(0));
|
|
@ -1,18 +1,18 @@
|
|||
package org.xbib.netty.http.client.test;
|
||||
|
||||
import io.netty.handler.codec.http.HttpMethod;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.xbib.netty.http.client.Request;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class RequestBuilderTest {
|
||||
class RequestBuilderTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(RequestBuilderTest.class.getName());
|
||||
|
||||
@Test
|
||||
public void testSimpleRequest() {
|
||||
void testSimpleRequest() {
|
||||
Request request = Request.builder(HttpMethod.GET).content("Hello", "text/plain").build();
|
||||
logger.log(Level.INFO, request.toString());
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package org.xbib.netty.http.client.test;
|
||||
|
||||
import io.netty.handler.codec.http.HttpMethod;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.xbib.TestBase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
import org.xbib.netty.http.client.Request;
|
||||
|
||||
|
@ -12,13 +11,15 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class SecureHttp1Test extends TestBase {
|
||||
@ExtendWith(NettyHttpExtension.class)
|
||||
class SecureHttpTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(SecureHttp1Test.class.getName());
|
||||
private static final Logger logger = Logger.getLogger(SecureHttpTest.class.getName());
|
||||
|
||||
@Test
|
||||
public void testHttp1() throws Exception {
|
||||
Client client = Client.builder().enableDebug().build();
|
||||
void testHttp1() throws Exception {
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
try {
|
||||
Request request = Request.get().url("https://www.google.com/").build()
|
||||
.setResponseListener(msg -> logger.log(Level.INFO, "got response: " +
|
||||
|
@ -32,39 +33,9 @@ public class SecureHttp1Test extends TestBase {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testParallelRequests() throws IOException {
|
||||
Client client = Client.builder().enableDebug().build();
|
||||
try {
|
||||
Request request1 = Request.builder(HttpMethod.GET)
|
||||
.url("https://google.com").setVersion("HTTP/1.1")
|
||||
.build()
|
||||
.setResponseListener(msg -> logger.log(Level.INFO, "got response: " +
|
||||
msg.headers().entries() +
|
||||
//msg.content().toString(StandardCharsets.UTF_8) +
|
||||
" status=" + msg.status().code()));
|
||||
Request request2 = Request.builder(HttpMethod.GET)
|
||||
.url("https://google.com").setVersion("HTTP/1.1")
|
||||
.build()
|
||||
.setResponseListener(msg -> logger.log(Level.INFO, "got response: " +
|
||||
msg.headers().entries() +
|
||||
//msg.content().toString(StandardCharsets.UTF_8) +
|
||||
" status=" + msg.status().code()));
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
client.execute(request1);
|
||||
client.execute(request2);
|
||||
}
|
||||
|
||||
} finally {
|
||||
client.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testSequentialRequests() throws Exception {
|
||||
Client client = Client.builder().enableDebug().build();
|
||||
void testSequentialRequests() throws Exception {
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
try {
|
||||
Request request1 = Request.get().url("https://google.com").build()
|
||||
.setResponseListener(msg -> logger.log(Level.INFO, "got response: " +
|
||||
|
@ -79,4 +50,33 @@ public class SecureHttp1Test extends TestBase {
|
|||
client.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParallelRequests() throws IOException {
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
try {
|
||||
Request request1 = Request.builder(HttpMethod.GET)
|
||||
.url("https://google.com").setVersion("HTTP/1.1")
|
||||
.build()
|
||||
.setResponseListener(msg -> logger.log(Level.INFO, "got response: " +
|
||||
msg.headers().entries() +
|
||||
" status=" + msg.status().code()));
|
||||
Request request2 = Request.builder(HttpMethod.GET)
|
||||
.url("https://google.com").setVersion("HTTP/1.1")
|
||||
.build()
|
||||
.setResponseListener(msg -> logger.log(Level.INFO, "got response: " +
|
||||
msg.headers().entries() +
|
||||
" status=" + msg.status().code()));
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
client.execute(request1);
|
||||
client.execute(request2);
|
||||
}
|
||||
|
||||
} finally {
|
||||
client.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
package org.xbib.netty.http.client.test;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.xbib.TestBase;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -10,18 +11,20 @@ import java.util.Set;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class ThreadLeakTest extends TestBase {
|
||||
@ExtendWith(NettyHttpExtension.class)
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class ThreadLeakTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ThreadLeakTest.class.getName());
|
||||
|
||||
@Test
|
||||
public void testForLeaks() throws IOException {
|
||||
void testForLeaks() throws IOException {
|
||||
Client client = new Client();
|
||||
client.shutdownGracefully();
|
||||
}
|
||||
|
||||
@After
|
||||
public void checkThreads() {
|
||||
@AfterAll
|
||||
void checkThreads() {
|
||||
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
|
||||
logger.log(Level.INFO, "threads = " + threadSet.size() );
|
||||
threadSet.forEach( thread -> logger.log(Level.INFO, thread.toString()));
|
||||
|
|
|
@ -1,19 +1,17 @@
|
|||
package org.xbib.netty.http.client.test;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.xbib.netty.http.client.Request;
|
||||
import org.xbib.netty.http.client.RequestBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class URITest {
|
||||
class URITest {
|
||||
|
||||
@Test
|
||||
public void testURIResolve() {
|
||||
void testURIResolve() {
|
||||
URI uri = URI.create("http://localhost");
|
||||
URI uri2 = uri.resolve("/path");
|
||||
assertEquals("http://localhost/path", uri2.toString());
|
||||
|
@ -23,7 +21,7 @@ public class URITest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testRequestURIs() {
|
||||
void testRequestURIs() {
|
||||
RequestBuilder httpRequestBuilder = Request.get();
|
||||
httpRequestBuilder.url("https://localhost").uri("/path");
|
||||
assertEquals("/path", httpRequestBuilder.build().relativeUri());
|
||||
|
|
|
@ -2,8 +2,7 @@ package org.xbib.netty.http.client.test;
|
|||
|
||||
import io.netty.handler.codec.http.FullHttpResponse;
|
||||
import io.netty.handler.proxy.HttpProxyHandler;
|
||||
import org.junit.Test;
|
||||
import org.xbib.TestBase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
import org.xbib.netty.http.client.Request;
|
||||
|
||||
|
@ -15,12 +14,12 @@ import java.util.function.Function;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class XbibTest extends TestBase {
|
||||
class XbibTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger("");
|
||||
private static final Logger logger = Logger.getLogger(XbibTest.class.getName());
|
||||
|
||||
@Test
|
||||
public void testXbibOrgWithDefaults() throws IOException {
|
||||
void testXbibOrgWithDefaults() throws IOException {
|
||||
Client client = new Client();
|
||||
try {
|
||||
Request request = Request.get().url("http://xbib.org")
|
||||
|
@ -36,7 +35,7 @@ public class XbibTest extends TestBase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testXbibOrgWithCompletableFuture() throws IOException {
|
||||
void testXbibOrgWithCompletableFuture() throws IOException {
|
||||
Client httpClient = Client.builder()
|
||||
.setTcpNodelay(true)
|
||||
.build();
|
||||
|
@ -66,7 +65,7 @@ public class XbibTest extends TestBase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testXbibOrgWithProxy() throws IOException {
|
||||
void testXbibOrgWithProxy() throws IOException {
|
||||
Client httpClient = Client.builder()
|
||||
.setHttpProxyHandler(new HttpProxyHandler(new InetSocketAddress("80.241.223.251", 8080)))
|
||||
.setConnectTimeoutMillis(30000)
|
||||
|
@ -87,7 +86,7 @@ public class XbibTest extends TestBase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testXbibOrgWithVeryShortReadTimeout() throws IOException {
|
||||
void testXbibOrgWithVeryShortReadTimeout() throws IOException {
|
||||
Client httpClient = Client.builder()
|
||||
.build();
|
||||
try {
|
||||
|
@ -106,7 +105,7 @@ public class XbibTest extends TestBase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testXbibTwoSequentialRequests() throws IOException {
|
||||
void testXbibTwoSequentialRequests() throws IOException {
|
||||
Client httpClient = new Client();
|
||||
try {
|
||||
httpClient.execute(Request.get()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package org.xbib.netty.http.hacks;
|
||||
package org.xbib.netty.http.client.test.hacks;
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
@ -26,9 +26,7 @@ import io.netty.handler.ssl.SslHandler;
|
|||
import io.netty.handler.ssl.SslProvider;
|
||||
import io.netty.handler.ssl.SupportedCipherSuiteFilter;
|
||||
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.xbib.TestBase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.net.ssl.SNIHostName;
|
||||
import javax.net.ssl.SNIServerName;
|
||||
|
@ -40,13 +38,12 @@ import java.util.concurrent.CompletableFuture;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Ignore
|
||||
public class Http2FramesTest extends TestBase {
|
||||
class Http2FramesTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(Http2FramesTest.class.getName());
|
||||
|
||||
@Test
|
||||
public void testHttp2Frames() throws Exception {
|
||||
void testHttp2Frames() throws Exception {
|
||||
final InetSocketAddress inetSocketAddress = new InetSocketAddress("webtide.com", 443);
|
||||
CompletableFuture<Boolean> completableFuture = new CompletableFuture<>();
|
||||
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
|
|
@ -1,4 +1,4 @@
|
|||
package org.xbib.netty.http.hacks;
|
||||
package org.xbib.netty.http.client.test.hacks;
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
|
@ -19,10 +19,9 @@ import io.netty.handler.codec.http.HttpMethod;
|
|||
import io.netty.handler.codec.http.HttpObjectAggregator;
|
||||
import io.netty.handler.codec.http.HttpVersion;
|
||||
import io.netty.util.AttributeKey;
|
||||
import org.junit.After;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.xbib.TestBase;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
|
@ -40,8 +39,8 @@ import java.util.logging.LogManager;
|
|||
import java.util.logging.Logger;
|
||||
import java.util.logging.SimpleFormatter;
|
||||
|
||||
@Ignore
|
||||
public class SimpleHttp1Test extends TestBase {
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
public class SimpleHttp1Test {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(SimpleHttp1Test.class.getName());
|
||||
|
||||
|
@ -62,7 +61,7 @@ public class SimpleHttp1Test extends TestBase {
|
|||
}
|
||||
}
|
||||
|
||||
@After
|
||||
@AfterAll
|
||||
public void checkThreads() {
|
||||
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
|
||||
logger.log(Level.INFO, "threads = " + threadSet.size() );
|
||||
|
@ -74,7 +73,7 @@ public class SimpleHttp1Test extends TestBase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testHttp1() throws Exception {
|
||||
void testHttp1() throws Exception {
|
||||
Client client = new Client();
|
||||
try {
|
||||
HttpTransport transport = client.newTransport("xbib.org", 80);
|
|
@ -1,4 +1,4 @@
|
|||
package org.xbib.netty.http.hacks;
|
||||
package org.xbib.netty.http.client.test.hacks;
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
|
@ -35,9 +35,7 @@ import io.netty.handler.ssl.SslProvider;
|
|||
import io.netty.handler.ssl.SupportedCipherSuiteFilter;
|
||||
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
||||
import io.netty.util.AttributeKey;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.xbib.TestBase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import java.io.IOException;
|
||||
|
@ -53,13 +51,12 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Ignore
|
||||
public class SimpleHttp2Test extends TestBase {
|
||||
class SimpleHttp2Test {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(SimpleHttp2Test.class.getName());
|
||||
|
||||
@Test
|
||||
public void testHttp2WithUpgrade() throws Exception {
|
||||
void testHttp2WithUpgrade() throws Exception {
|
||||
Client client = new Client();
|
||||
try {
|
||||
Http2Transport transport = client.newTransport("webtide.com", 443);
|
|
@ -0,0 +1,17 @@
|
|||
package org.xbib.netty.http.client.test.pool;
|
||||
|
||||
import io.netty.channel.epoll.Epoll;
|
||||
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
|
||||
import org.junit.jupiter.api.extension.ExecutionCondition;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
|
||||
public class DisableTestCondition implements ExecutionCondition {
|
||||
@Override
|
||||
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
|
||||
if (Epoll.isAvailable()) {
|
||||
return ConditionEvaluationResult.enabled("Test enabled");
|
||||
} else {
|
||||
return ConditionEvaluationResult.disabled("Test disabled");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package org.xbib.netty.http.client.test.pool;
|
||||
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ExtendWith(DisableTestCondition.class)
|
||||
public @interface DisabledIfEpolllNotAvailable {
|
||||
}
|
|
@ -17,17 +17,14 @@ import io.netty.channel.epoll.EpollSocketChannel;
|
|||
import io.netty.channel.socket.SocketChannel;
|
||||
|
||||
import io.netty.handler.codec.http.HttpVersion;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.xbib.netty.http.common.HttpAddress;
|
||||
import org.xbib.netty.http.client.pool.Pool;
|
||||
import org.xbib.netty.http.client.pool.BoundedChannelPool;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -40,8 +37,12 @@ import java.util.concurrent.atomic.LongAdder;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Ignore
|
||||
public class EpollTest {
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
@DisabledIfEpolllNotAvailable
|
||||
class EpollTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(EpollTest.class.getName());
|
||||
|
||||
|
@ -64,8 +65,8 @@ public class EpollTest {
|
|||
|
||||
private EventLoopGroup eventLoopGroup;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
@BeforeAll
|
||||
void setUp() throws Exception {
|
||||
mockEpollServer = new MockEpollServer(12345, FAIL_EVERY_ATTEMPT);
|
||||
Semaphore semaphore = new Semaphore(CONCURRENCY);
|
||||
eventLoopGroup = new EpollEventLoopGroup();
|
||||
|
@ -86,15 +87,15 @@ public class EpollTest {
|
|||
channelPool.prepare(CONCURRENCY);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
@AfterAll
|
||||
void tearDown() throws Exception {
|
||||
channelPool.close();
|
||||
eventLoopGroup.shutdownGracefully();
|
||||
mockEpollServer.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPoolEpoll() throws Exception {
|
||||
void testPoolEpoll() throws Exception {
|
||||
LongAdder longAdder = new LongAdder();
|
||||
ExecutorService executor = Executors.newFixedThreadPool(CONCURRENCY);
|
||||
for(int i = 0; i < CONCURRENCY; i ++) {
|
||||
|
@ -146,7 +147,7 @@ public class EpollTest {
|
|||
|
||||
private final AtomicLong reqCounter;
|
||||
|
||||
public MockEpollServer(int port, int dropEveryRequest) throws InterruptedException {
|
||||
MockEpollServer(int port, int dropEveryRequest) throws InterruptedException {
|
||||
dispatchGroup = new EpollEventLoopGroup();
|
||||
workerGroup = new EpollEventLoopGroup();
|
||||
reqCounter = new AtomicLong(0);
|
||||
|
|
|
@ -16,9 +16,10 @@ import io.netty.channel.socket.SocketChannel;
|
|||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.codec.http.HttpVersion;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.xbib.netty.http.common.HttpAddress;
|
||||
import org.xbib.netty.http.client.pool.Pool;
|
||||
import org.xbib.netty.http.client.pool.BoundedChannelPool;
|
||||
|
@ -35,10 +36,11 @@ import java.util.concurrent.atomic.LongAdder;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class NioTest {
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class NioTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(NioTest.class.getName());
|
||||
|
||||
|
@ -61,8 +63,8 @@ public class NioTest {
|
|||
|
||||
private EventLoopGroup eventLoopGroup;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
@BeforeAll
|
||||
void setUp() throws Exception {
|
||||
mockNioServer = new MockNioServer(12345, FAIL_EVERY_ATTEMPT);
|
||||
Semaphore semaphore = new Semaphore(CONCURRENCY);
|
||||
eventLoopGroup = new NioEventLoopGroup();
|
||||
|
@ -83,15 +85,15 @@ public class NioTest {
|
|||
channelPool.prepare(CONCURRENCY);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
@AfterAll
|
||||
void tearDown() throws Exception {
|
||||
channelPool.close();
|
||||
eventLoopGroup.shutdownGracefully();
|
||||
mockNioServer.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPoolNio() throws Exception {
|
||||
void testPoolNio() throws Exception {
|
||||
LongAdder longAdder = new LongAdder();
|
||||
ExecutorService executor = Executors.newFixedThreadPool(CONCURRENCY);
|
||||
for(int i = 0; i < CONCURRENCY; i ++) {
|
||||
|
@ -142,7 +144,7 @@ public class NioTest {
|
|||
|
||||
private final AtomicLong reqCounter;
|
||||
|
||||
public MockNioServer(int port, int dropEveryRequest) throws InterruptedException {
|
||||
MockNioServer(int port, int dropEveryRequest) throws InterruptedException {
|
||||
dispatchGroup = new NioEventLoopGroup();
|
||||
workerGroup = new NioEventLoopGroup();
|
||||
reqCounter = new AtomicLong(0);
|
||||
|
|
|
@ -9,16 +9,13 @@ import io.netty.channel.socket.nio.NioServerSocketChannel;
|
|||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.codec.http.HttpVersion;
|
||||
import io.netty.util.AttributeKey;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.xbib.netty.http.common.HttpAddress;
|
||||
import org.xbib.netty.http.client.pool.BoundedChannelPool;
|
||||
import org.xbib.netty.http.client.pool.Pool;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
@ -30,11 +27,10 @@ import java.util.concurrent.atomic.LongAdder;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class PoolTest {
|
||||
class PoolTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(PoolTest.class.getName());
|
||||
|
||||
|
@ -42,30 +38,11 @@ public class PoolTest {
|
|||
|
||||
private static final int BATCH_SIZE = 0x1000;
|
||||
|
||||
private int nodeCount;
|
||||
|
||||
private ConcurrentMap<HttpAddress, LongAdder> nodeFreq = new ConcurrentHashMap<>();
|
||||
|
||||
@Parameterized.Parameters
|
||||
public static Collection<Object[]> generateData() {
|
||||
return Arrays.asList(new Object[][] {
|
||||
{1, 1},
|
||||
{10, 1},
|
||||
{10, 2},
|
||||
//{10, 5},
|
||||
//{10, 10},
|
||||
{100, 1},
|
||||
{100, 2},
|
||||
//{100, 5},
|
||||
//{100, 10},
|
||||
//{1000, 1},
|
||||
//{1000, 2},
|
||||
//{1000, 5},
|
||||
//{1000, 10}
|
||||
});
|
||||
}
|
||||
|
||||
public PoolTest(int concurrencyLevel, int nodeCount) throws InterruptedException {
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = {1,10,100})
|
||||
void testPool(int concurrencyLevel) throws InterruptedException {
|
||||
ConcurrentMap<HttpAddress, LongAdder> nodeFreq = new ConcurrentHashMap<>();
|
||||
int nodecount = 2;
|
||||
|
||||
ServerBootstrap serverBootstrap = new ServerBootstrap()
|
||||
.group(new NioEventLoopGroup())
|
||||
|
@ -77,9 +54,8 @@ public class PoolTest {
|
|||
});
|
||||
Channel serverChannel = serverBootstrap.bind("localhost", 8008).sync().channel();
|
||||
|
||||
this.nodeCount = nodeCount;
|
||||
List<HttpAddress> nodes = new ArrayList<>();
|
||||
for (int i = 0; i < nodeCount; i ++) {
|
||||
for (int i = 0; i < nodecount; i ++) {
|
||||
nodes.add(HttpAddress.http1("localhost", 8008));
|
||||
}
|
||||
try (Pool<Channel> pool = new BoundedChannelPool<>(new Semaphore(concurrencyLevel), HttpVersion.HTTP_1_1,
|
||||
|
@ -127,25 +103,16 @@ public class PoolTest {
|
|||
} finally {
|
||||
serverChannel.close();
|
||||
long connCountSum = nodeFreq.values().stream().mapToLong(LongAdder::sum).sum();
|
||||
logger.log(Level.INFO, "concurrency = " + concurrencyLevel + ", nodes = " + nodeCount + " -> rate: " +
|
||||
logger.log(Level.INFO, "concurrency = " + concurrencyLevel + ", nodes = " + nodecount + " -> rate: " +
|
||||
connCountSum / TEST_STEP_TIME_SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNodeFrequency() {
|
||||
if (nodeCount > 1) {
|
||||
long connCountSum = nodeFreq.values().stream().mapToLong(LongAdder::sum).sum();
|
||||
long avgConnCountPerNode = connCountSum / nodeCount;
|
||||
long avgConnCountPerNode = connCountSum / 2;
|
||||
for (HttpAddress nodeAddr: nodeFreq.keySet()) {
|
||||
assertTrue(nodeFreq.get(nodeAddr).sum() > 0);
|
||||
assertEquals("Node count: " + nodeCount + ", node: " + nodeAddr
|
||||
assertEquals(/*"Node count: " + nodeCount + ", node: " + nodeAddr
|
||||
+ ", expected connection count: " + avgConnCountPerNode + ", actual: "
|
||||
+ nodeFreq.get(nodeAddr).sum(),
|
||||
+ nodeFreq.get(nodeAddr).sum(),*/
|
||||
avgConnCountPerNode, nodeFreq.get(nodeAddr).sum(), 1.5 * avgConnCountPerNode);
|
||||
}
|
||||
} else {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package org.xbib.netty.http.client.test.pool;
|
||||
|
||||
import io.netty.handler.codec.http.HttpVersion;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.net.URL;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
import org.xbib.TestBase;
|
||||
import org.xbib.netty.http.client.listener.ResponseListener;
|
||||
import org.xbib.netty.http.client.test.NettyHttpExtension;
|
||||
import org.xbib.netty.http.common.HttpAddress;
|
||||
import org.xbib.netty.http.client.Request;
|
||||
|
||||
|
@ -18,12 +19,13 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class PooledClientTest extends TestBase {
|
||||
@ExtendWith(NettyHttpExtension.class)
|
||||
class PooledClientTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger("");
|
||||
private static final Logger logger = Logger.getLogger(PooledClientTest.class.getName());
|
||||
|
||||
@Test
|
||||
public void testPooledClientWithSingleNode() throws IOException {
|
||||
void testPooledClientWithSingleNode() throws IOException {
|
||||
int loop = 10;
|
||||
int threads = Runtime.getRuntime().availableProcessors();
|
||||
URL url = URL.from("https://fl-test.hbz-nrw.de/app/fl");
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
package org.xbib.netty.http.client.test.rest;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.xbib.netty.http.client.rest.RestClient;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class RestClientTest {
|
||||
class RestClientTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(RestClientTest.class.getName());
|
||||
|
||||
@Test
|
||||
public void testSimpleGet() throws IOException {
|
||||
void testSimpleGet() throws IOException {
|
||||
String result = RestClient.get("http://xbib.org").asString();
|
||||
logger.info(result);
|
||||
}
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
package org.xbib.netty.http.client.test.retry;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.xbib.netty.http.client.retry.BackOff;
|
||||
import org.xbib.netty.http.client.retry.ExponentialBackOff;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link ExponentialBackOff}.
|
||||
*/
|
||||
public class ExponentialBackOffTest {
|
||||
class ExponentialBackOffTest {
|
||||
|
||||
@Test
|
||||
public void testConstructor() {
|
||||
void testConstructor() {
|
||||
ExponentialBackOff backOffPolicy = new ExponentialBackOff();
|
||||
assertEquals(ExponentialBackOff.DEFAULT_INITIAL_INTERVAL_MILLIS,
|
||||
backOffPolicy.getInitialIntervalMillis());
|
||||
|
@ -29,7 +30,7 @@ public class ExponentialBackOffTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testBuilder() {
|
||||
void testBuilder() {
|
||||
ExponentialBackOff backOffPolicy = new ExponentialBackOff.Builder().build();
|
||||
assertEquals(ExponentialBackOff.DEFAULT_INITIAL_INTERVAL_MILLIS,
|
||||
backOffPolicy.getInitialIntervalMillis());
|
||||
|
@ -64,7 +65,7 @@ public class ExponentialBackOffTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testBackOff() {
|
||||
void testBackOff() {
|
||||
int testInitialInterval = 500;
|
||||
double testRandomizationFactor = 0.1;
|
||||
double testMultiplier = 2.0;
|
||||
|
@ -90,7 +91,7 @@ public class ExponentialBackOffTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testGetRandomizedInterval() {
|
||||
void testGetRandomizedInterval() {
|
||||
// 33% chance of being 1.
|
||||
assertEquals(1, ExponentialBackOff.getRandomValueFromInterval(0.5, 0, 2));
|
||||
assertEquals(1, ExponentialBackOff.getRandomValueFromInterval(0.5, 0.33, 2));
|
||||
|
@ -103,14 +104,14 @@ public class ExponentialBackOffTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testGetElapsedTimeMillis() {
|
||||
void testGetElapsedTimeMillis() {
|
||||
ExponentialBackOff backOffPolicy = new ExponentialBackOff.Builder().setNanoClock(new MyNanoClock()).build();
|
||||
long elapsedTimeMillis = backOffPolicy.getElapsedTimeMillis();
|
||||
assertEquals("elapsedTimeMillis=" + elapsedTimeMillis, 1000, elapsedTimeMillis);
|
||||
assertEquals(1000, elapsedTimeMillis);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxElapsedTime() {
|
||||
void testMaxElapsedTime() {
|
||||
ExponentialBackOff backOffPolicy =
|
||||
new ExponentialBackOff.Builder().setNanoClock(new MyNanoClock(10000)).build();
|
||||
assertTrue(backOffPolicy.nextBackOffMillis() != BackOff.STOP);
|
||||
|
@ -121,7 +122,7 @@ public class ExponentialBackOffTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testBackOffOverflow() {
|
||||
void testBackOffOverflow() {
|
||||
int testInitialInterval = Integer.MAX_VALUE / 2;
|
||||
double testMultiplier = 2.1;
|
||||
int testMaxInterval = Integer.MAX_VALUE;
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
package org.xbib.netty.http.client.test.retry;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.xbib.netty.http.client.retry.BackOff;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/**
|
||||
* Tests {@link MockBackOff}.
|
||||
*/
|
||||
public class MockBackOffTest {
|
||||
class MockBackOffTest {
|
||||
|
||||
@Test
|
||||
public void testNextBackOffMillis() throws IOException {
|
||||
void testNextBackOffMillis() throws IOException {
|
||||
subtestNextBackOffMillis(0, new MockBackOff());
|
||||
subtestNextBackOffMillis(BackOff.STOP, new MockBackOff().setBackOffMillis(BackOff.STOP));
|
||||
subtestNextBackOffMillis(42, new MockBackOff().setBackOffMillis(42));
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
dependencies {
|
||||
compile "org.xbib:net-url:${project.property('xbib-net-url.version')}"
|
||||
compile "io.netty:netty-codec-http2:${project.property('netty.version')}"
|
||||
implementation "org.xbib:net-url:${project.property('xbib-net-url.version')}"
|
||||
implementation "io.netty:netty-codec-http2:${project.property('netty.version')}"
|
||||
}
|
||||
|
|
6
netty-http-server-rest/build.gradle
Normal file
6
netty-http-server-rest/build.gradle
Normal file
|
@ -0,0 +1,6 @@
|
|||
dependencies {
|
||||
implementation project(":netty-http-server")
|
||||
implementation "io.netty:netty-codec-http2:${project.property('netty.version')}"
|
||||
implementation "org.xbib:net-url:${project.property('xbib-net-url.version')}"
|
||||
implementation "org.xbib:guice:${project.property('xbib-guice.version')}"
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package org.xbib.netty.http.server.rest;
|
||||
|
||||
public class Rest {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package org.xbib.netty.http.server.rest;
|
||||
|
||||
public class RestBuilder {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package org.xbib.netty.http.server.rest;
|
||||
|
||||
public class RestConfig {
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package org.xbib.netty.http.server.rest;
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Server name.
|
||||
*/
|
||||
public final class RestName {
|
||||
|
||||
/**
|
||||
* The default value for {@code Server} header.
|
||||
*/
|
||||
private static final String SERVER_NAME = String.format("RestServer/%s (Java/%s/%s) (Netty/%s)",
|
||||
httpServerVersion(), javaVendor(), javaVersion(), nettyVersion());
|
||||
|
||||
private RestName() {
|
||||
}
|
||||
|
||||
public static String getServerName() {
|
||||
return SERVER_NAME;
|
||||
}
|
||||
|
||||
private static String httpServerVersion() {
|
||||
return Optional.ofNullable(Rest.class.getPackage().getImplementationVersion())
|
||||
.orElse("unknown");
|
||||
}
|
||||
|
||||
private static String javaVendor() {
|
||||
return Optional.ofNullable(System.getProperty("java.vendor"))
|
||||
.orElse("unknown");
|
||||
}
|
||||
|
||||
private static String javaVersion() {
|
||||
return Optional.ofNullable(System.getProperty("java.version"))
|
||||
.orElse("unknown");
|
||||
}
|
||||
|
||||
private static String nettyVersion() {
|
||||
return Optional.ofNullable(Bootstrap.class.getPackage().getImplementationVersion())
|
||||
.orElse("unknown");
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,10 +1,10 @@
|
|||
dependencies {
|
||||
compile project(":netty-http-common")
|
||||
compile "io.netty:netty-handler:${project.property('netty.version')}"
|
||||
compile "io.netty:netty-transport-native-epoll:${project.property('netty.version')}"
|
||||
compile "io.netty:netty-tcnative-boringssl-static:${project.property('tcnative.version')}"
|
||||
compile "org.bouncycastle:bcpkix-jdk15on:${project.property('bouncycastle.version')}"
|
||||
|
||||
testCompile project(":netty-http-client")
|
||||
testCompile "junit:junit:${project.property('junit.version')}"
|
||||
implementation project(":netty-http-common")
|
||||
implementation "io.netty:netty-handler:${project.property('netty.version')}"
|
||||
implementation "io.netty:netty-transport-native-epoll:${project.property('netty.version')}"
|
||||
implementation "io.netty:netty-tcnative-boringssl-static:${project.property('tcnative.version')}"
|
||||
implementation "io.netty:netty-codec-http2:${project.property('netty.version')}"
|
||||
implementation "org.xbib:net-url:${project.property('xbib-net-url.version')}"
|
||||
implementation "org.bouncycastle:bcpkix-jdk15on:${project.property('bouncycastle.version')}"
|
||||
testImplementation project(":netty-http-client")
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ import io.netty.handler.ssl.SslContextBuilder;
|
|||
import io.netty.util.DomainNameMapping;
|
||||
import io.netty.util.DomainNameMappingBuilder;
|
||||
import org.xbib.netty.http.common.HttpAddress;
|
||||
import org.xbib.netty.http.server.context.VirtualServer;
|
||||
import org.xbib.netty.http.server.endpoint.NamedServer;
|
||||
import org.xbib.netty.http.server.handler.http.HttpChannelInitializer;
|
||||
import org.xbib.netty.http.server.handler.http2.Http2ChannelInitializer;
|
||||
import org.xbib.netty.http.server.transport.HttpServerTransport;
|
||||
|
@ -73,7 +73,7 @@ public final class Server {
|
|||
|
||||
private final ServerBootstrap bootstrap;
|
||||
|
||||
private final Map<String, VirtualServer> virtualServerMap;
|
||||
private final Map<String, NamedServer> virtualServerMap;
|
||||
|
||||
private ChannelFuture channelFuture;
|
||||
|
||||
|
@ -118,11 +118,11 @@ public final class Server {
|
|||
bootstrap.handler(new LoggingHandler("bootstrap-server", serverConfig.getDebugLogLevel()));
|
||||
}
|
||||
this.virtualServerMap = new HashMap<>();
|
||||
for (VirtualServer virtualServer : serverConfig.getVirtualServers()) {
|
||||
String name = virtualServer.getName();
|
||||
virtualServerMap.put(name, virtualServer);
|
||||
for (String alias : virtualServer.getAliases()) {
|
||||
virtualServerMap.put(alias, virtualServer);
|
||||
for (NamedServer namedServer : serverConfig.getNamedServers()) {
|
||||
String name = namedServer.getName();
|
||||
virtualServerMap.put(name, namedServer);
|
||||
for (String alias : namedServer.getAliases()) {
|
||||
virtualServerMap.put(alias, namedServer);
|
||||
}
|
||||
}
|
||||
DomainNameMapping<SslContext> domainNameMapping = null;
|
||||
|
@ -136,8 +136,8 @@ public final class Server {
|
|||
}
|
||||
SslContext sslContext = sslContextBuilder.build();
|
||||
DomainNameMappingBuilder<SslContext> mappingBuilder = new DomainNameMappingBuilder<>(sslContext);
|
||||
for (VirtualServer virtualServer : serverConfig.getVirtualServers()) {
|
||||
String name = virtualServer.getName();
|
||||
for (NamedServer namedServer : serverConfig.getNamedServers()) {
|
||||
String name = namedServer.getName();
|
||||
mappingBuilder.add(name == null ? "*" : name, sslContext);
|
||||
}
|
||||
domainNameMapping = mappingBuilder.build();
|
||||
|
@ -169,11 +169,11 @@ public final class Server {
|
|||
* the default virtual host
|
||||
* @return the virtual host with the given name, or null if it doesn't exist
|
||||
*/
|
||||
public VirtualServer getVirtualServer(String name) {
|
||||
public NamedServer getVirtualServer(String name) {
|
||||
return virtualServerMap.get(name);
|
||||
}
|
||||
|
||||
public VirtualServer getDefaultVirtualServer() {
|
||||
public NamedServer getDefaultVirtualServer() {
|
||||
return virtualServerMap.get(null);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,8 @@ import io.netty.handler.ssl.CipherSuiteFilter;
|
|||
import io.netty.handler.ssl.SslProvider;
|
||||
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
||||
import org.xbib.netty.http.common.HttpAddress;
|
||||
import org.xbib.netty.http.server.context.VirtualServer;
|
||||
import org.xbib.netty.http.server.endpoint.Handler;
|
||||
import org.xbib.netty.http.server.endpoint.NamedServer;
|
||||
import org.xbib.netty.http.server.security.tls.SelfSignedCertificate;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
|
@ -224,8 +225,16 @@ public class ServerBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public ServerBuilder addVirtualServer(VirtualServer virtualServer) {
|
||||
this.serverConfig.addVirtualServer(virtualServer);
|
||||
public ServerBuilder addServer(NamedServer namedServer) {
|
||||
this.serverConfig.add(namedServer);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ServerBuilder addHandler(String path, Handler handler, String... methods) {
|
||||
if (serverConfig.getNamedServers().isEmpty()) {
|
||||
serverConfig.add(new NamedServer());
|
||||
}
|
||||
serverConfig.getNamedServers().getLast().addHandler(path, handler, methods);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,12 +10,14 @@ import io.netty.handler.ssl.OpenSsl;
|
|||
import io.netty.handler.ssl.SslProvider;
|
||||
import io.netty.handler.ssl.SupportedCipherSuiteFilter;
|
||||
import org.xbib.netty.http.common.HttpAddress;
|
||||
import org.xbib.netty.http.server.context.VirtualServer;
|
||||
import org.xbib.netty.http.server.endpoint.NamedServer;
|
||||
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class ServerConfig {
|
||||
|
@ -117,7 +119,7 @@ public class ServerConfig {
|
|||
|
||||
/**
|
||||
* This is Netty's default.
|
||||
* See {@link io.netty.handler.codec.MessageAggregator#DEFAULT_MAX_COMPOSITEBUFFER_COMPONENTS}.
|
||||
* See {@link io.netty.handler.codec.MessageAggregator#maxCumulationBufferComponents()}.
|
||||
*/
|
||||
int MAX_COMPOSITE_BUFFER_COMPONENTS = 1024;
|
||||
|
||||
|
@ -225,15 +227,15 @@ public class ServerConfig {
|
|||
|
||||
private String keyPassword;
|
||||
|
||||
private List<VirtualServer> virtualServers;
|
||||
private Deque<NamedServer> namedServers;
|
||||
|
||||
private TrustManagerFactory trustManagerFactory = TRUST_MANAGER_FACTORY;
|
||||
|
||||
private KeyStore trustManagerKeyStore = null;
|
||||
|
||||
public ServerConfig() {
|
||||
this.virtualServers = new ArrayList<>();
|
||||
addVirtualServer(new VirtualServer(null));
|
||||
this.namedServers = new LinkedList<>();
|
||||
add(new NamedServer(null));
|
||||
}
|
||||
|
||||
public ServerConfig enableDebug() {
|
||||
|
@ -512,13 +514,13 @@ public class ServerConfig {
|
|||
return keyPassword;
|
||||
}
|
||||
|
||||
public ServerConfig addVirtualServer(VirtualServer virtualServer) {
|
||||
this.virtualServers.add(virtualServer);
|
||||
public ServerConfig add(NamedServer namedServer) {
|
||||
this.namedServers.add(namedServer);
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<VirtualServer> getVirtualServers() {
|
||||
return virtualServers;
|
||||
public Deque<NamedServer> getNamedServers() {
|
||||
return namedServers;
|
||||
}
|
||||
|
||||
public ServerConfig setTrustManagerFactory(TrustManagerFactory trustManagerFactory) {
|
||||
|
|
|
@ -12,7 +12,7 @@ public final class ServerName {
|
|||
/**
|
||||
* The default value for {@code Server} header.
|
||||
*/
|
||||
private static final String SERVER_NAME = String.format("XbibHttpServer/%s (Java/%s/%s) (Netty/%s)",
|
||||
private static final String SERVER_NAME = String.format("NettyHttpServer/%s (Java/%s/%s) (Netty/%s)",
|
||||
httpServerVersion(), javaVendor(), javaVersion(), nettyVersion());
|
||||
|
||||
private ServerName() {
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
package org.xbib.netty.http.server.context;
|
||||
|
||||
import org.xbib.netty.http.server.transport.ServerRequest;
|
||||
import org.xbib.netty.http.server.transport.ServerResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A {@code ContextHandler} is capable of serving content for resources within its context.
|
||||
*
|
||||
* @see VirtualServer#addContext
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ContextHandler {
|
||||
|
||||
/**
|
||||
* Serves the given request using the given response.
|
||||
*
|
||||
* @param serverRequest the request to be served
|
||||
* @param serverResponse the response to be filled
|
||||
* @throws IOException if an IO error occurs
|
||||
*/
|
||||
void serve(ServerRequest serverRequest, ServerResponse serverResponse) throws IOException;
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
package org.xbib.netty.http.server.context;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The {@code ContextInfo} class holds a single context's information.
|
||||
*/
|
||||
public class ContextInfo {
|
||||
|
||||
private final VirtualServer virtualServer;
|
||||
|
||||
private final Map<String, ContextHandler> methodHandlerMap;
|
||||
|
||||
public ContextInfo(VirtualServer virtualServer) {
|
||||
this.virtualServer = virtualServer;
|
||||
this.methodHandlerMap = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the map of supported HTTP methods and their corresponding handlers.
|
||||
*
|
||||
* @return the map of supported HTTP methods and their corresponding handlers
|
||||
*/
|
||||
public Map<String, ContextHandler> getMethodHandlerMap() {
|
||||
return methodHandlerMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds (or replaces) a context handler for the given HTTP methods.
|
||||
*
|
||||
* @param handler the context handler
|
||||
* @param methods the HTTP methods supported by the handler (default is "GET")
|
||||
*/
|
||||
public void addHandler(ContextHandler handler, String... methods) {
|
||||
if (methods.length == 0) {
|
||||
methodHandlerMap.put("GET", handler);
|
||||
virtualServer.getMethods().add("GET");
|
||||
} else {
|
||||
for (String method : methods) {
|
||||
methodHandlerMap.put(method, handler);
|
||||
virtualServer.getMethods().add(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.xbib.netty.http.server.context;
|
||||
package org.xbib.netty.http.server.endpoint;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
@ -16,19 +16,19 @@ import java.nio.file.Files;
|
|||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class ClasspathContextHandler implements ContextHandler {
|
||||
public class ClasspathHandler implements Handler {
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
private final String prefix;
|
||||
|
||||
public ClasspathContextHandler(ClassLoader classLoader, String prefix) {
|
||||
public ClasspathHandler(ClassLoader classLoader, String prefix) {
|
||||
this.classLoader = classLoader;
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serve(ServerRequest serverRequest, ServerResponse serverResponse) throws IOException {
|
||||
public void handle(ServerRequest serverRequest, ServerResponse serverResponse) throws IOException {
|
||||
String contextPath = serverRequest.getContextPath();
|
||||
URL url = classLoader.getResource(prefix + contextPath);
|
||||
if (url != null) {
|
|
@ -1,4 +1,4 @@
|
|||
package org.xbib.netty.http.server.context;
|
||||
package org.xbib.netty.http.server.endpoint;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
|
@ -7,11 +7,11 @@ import java.lang.annotation.Target;
|
|||
|
||||
/**
|
||||
* The {@code Context} annotation decorates methods which are mapped
|
||||
* to a context (path) within the server, and provide its contents.
|
||||
* to a context path within the server, and provide its contents.
|
||||
* The annotated methods must have the same signature and contract
|
||||
* as {@link ContextHandler#serve}, but can have arbitrary names.
|
||||
* as {@link Handler#handle}, but can have arbitrary names.
|
||||
*
|
||||
* @see VirtualServer#addContexts(Object)
|
||||
* @see NamedServer#addHandlers(Object)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
|
@ -1,4 +1,4 @@
|
|||
package org.xbib.netty.http.server.context;
|
||||
package org.xbib.netty.http.server.endpoint;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
|
@ -13,19 +13,19 @@ import java.nio.channels.SeekableByteChannel;
|
|||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class DirectoryContextHandler implements ContextHandler {
|
||||
public class DirectoryHandler implements Handler {
|
||||
|
||||
private Path path;
|
||||
|
||||
private ByteBufAllocator allocator;
|
||||
|
||||
public DirectoryContextHandler(Path path, ByteBufAllocator allocator) {
|
||||
public DirectoryHandler(Path path, ByteBufAllocator allocator) {
|
||||
this.path = path;
|
||||
this.allocator = allocator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serve(ServerRequest serverRequest, ServerResponse serverResponse) throws IOException {
|
||||
public void handle(ServerRequest serverRequest, ServerResponse serverResponse) throws IOException {
|
||||
String uri = serverRequest.getRequest().uri();
|
||||
Path p = path.resolve(uri);
|
||||
ByteBuf byteBuf = read(allocator, p);
|
|
@ -0,0 +1,46 @@
|
|||
package org.xbib.netty.http.server.endpoint;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The {@code Endpoint} class holds an endpoint information.
|
||||
*/
|
||||
public class Endpoint {
|
||||
|
||||
private final NamedServer namedServer;
|
||||
|
||||
private final Map<String, Handler> handlerMap;
|
||||
|
||||
public Endpoint(NamedServer namedServer) {
|
||||
this.namedServer = namedServer;
|
||||
this.handlerMap = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the map of supported HTTP methods and their corresponding handlers.
|
||||
*
|
||||
* @return the map of supported HTTP methods and their corresponding handlers
|
||||
*/
|
||||
public Map<String, Handler> getHandlerMap() {
|
||||
return handlerMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds (or replaces) a handler for the given HTTP methods.
|
||||
*
|
||||
* @param handler the handler
|
||||
* @param methods the HTTP methods supported by the handler (default is "GET")
|
||||
*/
|
||||
public void addHandler(Handler handler, String... methods) {
|
||||
if (methods.length == 0) {
|
||||
handlerMap.put("GET", handler);
|
||||
namedServer.getMethods().add("GET");
|
||||
} else {
|
||||
for (String method : methods) {
|
||||
handlerMap.put(method, handler);
|
||||
namedServer.getMethods().add(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package org.xbib.netty.http.server.endpoint;
|
||||
|
||||
import org.xbib.netty.http.server.transport.ServerRequest;
|
||||
import org.xbib.netty.http.server.transport.ServerResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A {@code Handler} is capable of serving content for resources within its context.
|
||||
*
|
||||
* @see NamedServer#addHandler
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Handler {
|
||||
|
||||
/**
|
||||
* Handles the given request by using the given response.
|
||||
*
|
||||
* @param serverRequest the request to be served
|
||||
* @param serverResponse the response to be generated
|
||||
* @throws IOException if an IO error occurs
|
||||
*/
|
||||
void handle(ServerRequest serverRequest, ServerResponse serverResponse) throws IOException;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.xbib.netty.http.server.context;
|
||||
package org.xbib.netty.http.server.endpoint;
|
||||
|
||||
import org.xbib.netty.http.server.transport.ServerRequest;
|
||||
import org.xbib.netty.http.server.transport.ServerResponse;
|
||||
|
@ -8,20 +8,19 @@ import java.lang.reflect.InvocationTargetException;
|
|||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* The {@code MethodContextHandler} services a context
|
||||
* by invoking a handler method on a specified object.
|
||||
* The {@code MethodHandler} invokes g a handler method on a specified object.
|
||||
* The method must have the same signature and contract as
|
||||
* {@link ContextHandler#serve}, but can have an arbitrary name.
|
||||
* {@link Handler#handle}, but can have an arbitrary name.
|
||||
*
|
||||
* @see VirtualServer#addContexts(Object)
|
||||
* @see NamedServer#addHandlers(Object)
|
||||
*/
|
||||
public class MethodContextHandler implements ContextHandler {
|
||||
public class MethodHandler implements Handler {
|
||||
|
||||
private final Method m;
|
||||
|
||||
private final Object obj;
|
||||
|
||||
public MethodContextHandler(Method m, Object obj) throws IllegalArgumentException {
|
||||
public MethodHandler(Method m, Object obj) throws IllegalArgumentException {
|
||||
this.m = m;
|
||||
this.obj = obj;
|
||||
Class<?>[] params = m.getParameterTypes();
|
||||
|
@ -34,7 +33,7 @@ public class MethodContextHandler implements ContextHandler {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void serve(ServerRequest serverRequest, ServerResponse serverResponse) throws IOException {
|
||||
public void handle(ServerRequest serverRequest, ServerResponse serverResponse) throws IOException {
|
||||
try {
|
||||
m.invoke(obj, serverRequest, serverResponse);
|
||||
} catch (InvocationTargetException ite) {
|
|
@ -0,0 +1,21 @@
|
|||
package org.xbib.netty.http.server.endpoint;
|
||||
|
||||
public class NamedEndpoint {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final Endpoint endpoint;
|
||||
|
||||
NamedEndpoint(String name, Endpoint endpoint) {
|
||||
this.name = name;
|
||||
this.endpoint = endpoint;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Endpoint getEndpoint() {
|
||||
return endpoint;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.xbib.netty.http.server.context;
|
||||
package org.xbib.netty.http.server.endpoint;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
|
@ -10,7 +10,7 @@ import java.util.Set;
|
|||
/**
|
||||
* The {@code VirtualServer} class represents a virtual server.
|
||||
*/
|
||||
public class VirtualServer {
|
||||
public class NamedServer {
|
||||
|
||||
private final String name;
|
||||
|
||||
|
@ -18,28 +18,28 @@ public class VirtualServer {
|
|||
|
||||
private final Set<String> methods;
|
||||
|
||||
private final ContextInfo emptyContext;
|
||||
private final Endpoint defaultEndpoint;
|
||||
|
||||
private final Map<String, ContextInfo> contexts;
|
||||
private final Map<String, Endpoint> endpointMap;
|
||||
|
||||
private volatile boolean allowGeneratedIndex;
|
||||
|
||||
public VirtualServer() {
|
||||
public NamedServer() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a VirtualServer with the given name.
|
||||
* Constructs a {@code NamedServer} with the given name.
|
||||
*
|
||||
* @param name the name, or null if it is the default server
|
||||
*/
|
||||
public VirtualServer(String name) {
|
||||
public NamedServer(String name) {
|
||||
this.name = name;
|
||||
this.aliases = new HashSet<>();
|
||||
this.methods = new HashSet<>();
|
||||
this.contexts = new HashMap<>();
|
||||
this.emptyContext = new ContextInfo(this);
|
||||
contexts.put("*", new ContextInfo(this)); // for "OPTIONS *"
|
||||
this.endpointMap = new HashMap<>();
|
||||
this.defaultEndpoint = new Endpoint(this);
|
||||
endpointMap.put("*", new Endpoint(this)); // for "OPTIONS *"
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -105,34 +105,36 @@ public class VirtualServer {
|
|||
* @param path the context's path (must start with '/')
|
||||
* @param handler the context handler for the given path
|
||||
* @param methods the HTTP methods supported by the context handler (default is "GET")
|
||||
* @return this virtual server
|
||||
* @throws IllegalArgumentException if path is malformed
|
||||
*/
|
||||
public VirtualServer addContext(String path, ContextHandler handler, String... methods) {
|
||||
public NamedServer addHandler(String path, Handler handler, String... methods) {
|
||||
if (path == null || !path.startsWith("/") && !path.equals("*")) {
|
||||
throw new IllegalArgumentException("invalid path: " + path);
|
||||
}
|
||||
String s = trimRight(path, '/');
|
||||
ContextInfo info = new ContextInfo(this);
|
||||
ContextInfo existing = contexts.putIfAbsent(s, info);
|
||||
Endpoint info = new Endpoint(this);
|
||||
Endpoint existing = endpointMap.putIfAbsent(s, info);
|
||||
info = existing != null ? existing : info;
|
||||
info.addHandler(handler, methods);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds contexts for all methods of the given object that
|
||||
* Adds handler for all methods of the given object that
|
||||
* are annotated with the {@link Context} annotation.
|
||||
*
|
||||
* @param o the object whose annotated methods are added
|
||||
* @return this virtual server
|
||||
* @throws IllegalArgumentException if a Context-annotated
|
||||
* method has an {@link Context invalid signature}
|
||||
*/
|
||||
public VirtualServer addContexts(Object o) throws IllegalArgumentException {
|
||||
public NamedServer addHandlers(Object o) throws IllegalArgumentException {
|
||||
for (Class<?> c = o.getClass(); c != null; c = c.getSuperclass()) {
|
||||
for (Method m : c.getDeclaredMethods()) {
|
||||
Context context = m.getAnnotation(Context.class);
|
||||
if (context != null) {
|
||||
addContext(context.value(), new MethodContextHandler(m, o), context.methods());
|
||||
addHandler(context.value(), new MethodHandler(m, o), context.methods());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -140,24 +142,24 @@ public class VirtualServer {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the context handler for the given path.
|
||||
* If a context is not found for the given path, the search is repeated for
|
||||
* Returns the endpoint for the given path.
|
||||
* If an endpoint is not found for the given path, the search is repeated for
|
||||
* its parent path, and so on until a base context is found. If neither the
|
||||
* given path nor any of its parents has a context, an empty context is returned.
|
||||
*
|
||||
* @param path the context's path
|
||||
* @return the context info for the given path, or an empty context if none exists
|
||||
*/
|
||||
public ContextPath getContextPath(String path) {
|
||||
public NamedEndpoint getNamedEndpoint(String path) {
|
||||
String s = trimRight(path, '/');
|
||||
ContextInfo info = null;
|
||||
Endpoint info = null;
|
||||
String hook = null;
|
||||
while (info == null && s != null) {
|
||||
hook = s;
|
||||
info = contexts.get(s);
|
||||
info = endpointMap.get(s);
|
||||
s = getParentPath(s);
|
||||
}
|
||||
return new ContextPath(hook, info != null ? info : emptyContext);
|
||||
return new NamedEndpoint(hook, info != null ? info : defaultEndpoint);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -190,24 +192,4 @@ public class VirtualServer {
|
|||
return slash == -1 ? null : s.substring(0, slash);
|
||||
}
|
||||
|
||||
public class ContextPath {
|
||||
|
||||
private final String hook;
|
||||
|
||||
private final ContextInfo contextInfo;
|
||||
|
||||
ContextPath(String hook, ContextInfo contextInfo) {
|
||||
this.hook = hook;
|
||||
this.contextInfo = contextInfo;
|
||||
}
|
||||
|
||||
public String getHook() {
|
||||
return hook;
|
||||
}
|
||||
|
||||
public ContextInfo getContextInfo() {
|
||||
return contextInfo;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.xbib.netty.http.server.context;
|
||||
package org.xbib.netty.http.server.endpoint;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
@ -13,11 +13,11 @@ import java.nio.channels.FileChannel;
|
|||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class NioContextHandler implements ContextHandler {
|
||||
public class NioHandler implements Handler {
|
||||
|
||||
private final Path prefix;
|
||||
|
||||
public NioContextHandler(Path prefix) {
|
||||
public NioHandler(Path prefix) {
|
||||
this.prefix = prefix;
|
||||
if (!Files.exists(prefix) || !Files.isDirectory(prefix)) {
|
||||
throw new IllegalArgumentException("prefix: " + prefix + " (not a directory");
|
||||
|
@ -25,7 +25,7 @@ public class NioContextHandler implements ContextHandler {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void serve(ServerRequest serverRequest, ServerResponse serverResponse) throws IOException {
|
||||
public void handle(ServerRequest serverRequest, ServerResponse serverResponse) throws IOException {
|
||||
String requestPath = serverRequest.getRequestPath();
|
||||
Path path = prefix.resolve(requestPath.substring(1)); // starts always with '/'
|
||||
if (Files.exists(path) && Files.isReadable(path)) {
|
|
@ -6,8 +6,9 @@ import io.netty.handler.codec.http.HttpHeaders;
|
|||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import io.netty.handler.codec.http.HttpVersion;
|
||||
import org.xbib.netty.http.server.Server;
|
||||
import org.xbib.netty.http.server.context.ContextHandler;
|
||||
import org.xbib.netty.http.server.context.VirtualServer;
|
||||
import org.xbib.netty.http.server.endpoint.Handler;
|
||||
import org.xbib.netty.http.server.endpoint.NamedEndpoint;
|
||||
import org.xbib.netty.http.server.endpoint.NamedServer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
@ -88,28 +89,28 @@ abstract class BaseServerTransport implements ServerTransport {
|
|||
protected static void handle(ServerRequest serverRequest, ServerResponse serverResponse) throws IOException {
|
||||
String method = serverRequest.getRequest().method().name();
|
||||
String path = serverRequest.getRequest().uri();
|
||||
VirtualServer virtualServer = serverRequest.getVirtualServer();
|
||||
VirtualServer.ContextPath contextPath = virtualServer.getContextPath(path);
|
||||
serverRequest.setContextPath(contextPath.getHook());
|
||||
Map<String, ContextHandler> methodHandlerMap = contextPath.getContextInfo().getMethodHandlerMap();
|
||||
NamedServer namedServer = serverRequest.getNamedServer();
|
||||
NamedEndpoint namedEndpoint = namedServer.getNamedEndpoint(path);
|
||||
serverRequest.setContextPath(namedEndpoint.getName());
|
||||
Map<String, Handler> methodHandlerMap = namedEndpoint.getEndpoint().getHandlerMap();
|
||||
// RFC 2616#5.1.1 - GET and HEAD must be supported
|
||||
if (method.equals("GET") || method.equals("HEAD") || methodHandlerMap.containsKey(method)) {
|
||||
ContextHandler handler = methodHandlerMap.get(method);
|
||||
Handler handler = methodHandlerMap.get(method);
|
||||
if (handler == null) {
|
||||
serverResponse.writeError(HttpResponseStatus.NOT_FOUND);
|
||||
} else {
|
||||
handler.serve(serverRequest, serverResponse);
|
||||
handler.handle(serverRequest, serverResponse);
|
||||
}
|
||||
} else {
|
||||
Set<String> methods = new LinkedHashSet<>(METHODS);
|
||||
// "*" is a special server-wide (no-context) request supported by OPTIONS
|
||||
boolean isServerOptions = path.equals("*") && method.equals("OPTIONS");
|
||||
methods.addAll(isServerOptions ? virtualServer.getMethods() : methodHandlerMap.keySet());
|
||||
methods.addAll(isServerOptions ? namedServer.getMethods() : methodHandlerMap.keySet());
|
||||
serverResponse.setHeader(HttpHeaderNames.ALLOW, String.join(", ", methods));
|
||||
if (method.equals("OPTIONS")) { // default OPTIONS handler
|
||||
serverResponse.setHeader(HttpHeaderNames.CONTENT_LENGTH, "0"); // RFC2616#9.2
|
||||
serverResponse.write(HttpResponseStatus.OK);
|
||||
} else if (virtualServer.getMethods().contains(method)) {
|
||||
} else if (namedServer.getMethods().contains(method)) {
|
||||
serverResponse.write(HttpResponseStatus.METHOD_NOT_ALLOWED); // supported by server, but not this context (nor built-in)
|
||||
} else {
|
||||
serverResponse.writeError(HttpResponseStatus.NOT_IMPLEMENTED); // unsupported method
|
||||
|
|
|
@ -8,7 +8,7 @@ import io.netty.handler.codec.http2.Http2Settings;
|
|||
import io.netty.handler.codec.http2.HttpConversionUtil;
|
||||
import org.xbib.netty.http.common.HttpAddress;
|
||||
import org.xbib.netty.http.server.Server;
|
||||
import org.xbib.netty.http.server.context.VirtualServer;
|
||||
import org.xbib.netty.http.server.endpoint.NamedServer;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -26,13 +26,13 @@ public class Http2ServerTransport extends BaseServerTransport {
|
|||
@Override
|
||||
public void requestReceived(ChannelHandlerContext ctx, FullHttpRequest fullHttpRequest, Integer sequenceId) throws IOException {
|
||||
int requestId = requestCounter.incrementAndGet();
|
||||
VirtualServer virtualServer = server.getVirtualServer(fullHttpRequest.headers().get(HttpHeaderNames.HOST));
|
||||
if (virtualServer == null) {
|
||||
virtualServer = server.getDefaultVirtualServer();
|
||||
NamedServer namedServer = server.getVirtualServer(fullHttpRequest.headers().get(HttpHeaderNames.HOST));
|
||||
if (namedServer == null) {
|
||||
namedServer = server.getDefaultVirtualServer();
|
||||
}
|
||||
HttpAddress httpAddress = server.getServerConfig().getAddress();
|
||||
Integer streamId = fullHttpRequest.headers().getInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_ID.text());
|
||||
ServerRequest serverRequest = new ServerRequest(virtualServer, httpAddress, fullHttpRequest,
|
||||
ServerRequest serverRequest = new ServerRequest(namedServer, httpAddress, fullHttpRequest,
|
||||
sequenceId, streamId, requestId);
|
||||
ServerResponse serverResponse = new Http2ServerResponse(serverRequest, ctx);
|
||||
if (acceptRequest(serverRequest, serverResponse)) {
|
||||
|
|
|
@ -7,7 +7,7 @@ import io.netty.handler.codec.http.HttpResponseStatus;
|
|||
import io.netty.handler.codec.http2.Http2Settings;
|
||||
import org.xbib.netty.http.common.HttpAddress;
|
||||
import org.xbib.netty.http.server.Server;
|
||||
import org.xbib.netty.http.server.context.VirtualServer;
|
||||
import org.xbib.netty.http.server.endpoint.NamedServer;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -26,12 +26,12 @@ public class HttpServerTransport extends BaseServerTransport {
|
|||
public void requestReceived(ChannelHandlerContext ctx, FullHttpRequest fullHttpRequest, Integer sequenceId)
|
||||
throws IOException {
|
||||
int requestId = requestCounter.incrementAndGet();
|
||||
VirtualServer virtualServer = server.getVirtualServer(fullHttpRequest.headers().get(HttpHeaderNames.HOST));
|
||||
if (virtualServer == null) {
|
||||
virtualServer = server.getDefaultVirtualServer();
|
||||
NamedServer namedServer = server.getVirtualServer(fullHttpRequest.headers().get(HttpHeaderNames.HOST));
|
||||
if (namedServer == null) {
|
||||
namedServer = server.getDefaultVirtualServer();
|
||||
}
|
||||
HttpAddress httpAddress = server.getServerConfig().getAddress();
|
||||
ServerRequest serverRequest = new ServerRequest(virtualServer, httpAddress, fullHttpRequest,
|
||||
ServerRequest serverRequest = new ServerRequest(namedServer, httpAddress, fullHttpRequest,
|
||||
sequenceId, null, requestId);
|
||||
ServerResponse serverResponse = new HttpServerResponse(serverRequest, ctx);
|
||||
if (acceptRequest(serverRequest, serverResponse)) {
|
||||
|
|
|
@ -2,14 +2,14 @@ package org.xbib.netty.http.server.transport;
|
|||
|
||||
import io.netty.handler.codec.http.FullHttpRequest;
|
||||
import org.xbib.netty.http.common.HttpAddress;
|
||||
import org.xbib.netty.http.server.context.VirtualServer;
|
||||
import org.xbib.netty.http.server.endpoint.NamedServer;
|
||||
|
||||
/**
|
||||
* The {@code ServerRequest} class encapsulates a single request.
|
||||
*/
|
||||
public class ServerRequest {
|
||||
|
||||
private final VirtualServer virtualServer;
|
||||
private final NamedServer namedServer;
|
||||
|
||||
private final HttpAddress httpAddress;
|
||||
|
||||
|
@ -23,9 +23,9 @@ public class ServerRequest {
|
|||
|
||||
private String contextPath;
|
||||
|
||||
public ServerRequest(VirtualServer virtualServer, HttpAddress httpAddress,
|
||||
public ServerRequest(NamedServer namedServer, HttpAddress httpAddress,
|
||||
FullHttpRequest httpRequest, Integer sequenceId, Integer streamId, Integer requestId) {
|
||||
this.virtualServer = virtualServer;
|
||||
this.namedServer = namedServer;
|
||||
this.httpAddress = httpAddress;
|
||||
this.httpRequest = httpRequest;
|
||||
this.sequenceId = sequenceId;
|
||||
|
@ -33,8 +33,8 @@ public class ServerRequest {
|
|||
this.requestId = requestId;
|
||||
}
|
||||
|
||||
public VirtualServer getVirtualServer() {
|
||||
return virtualServer;
|
||||
public NamedServer getNamedServer() {
|
||||
return namedServer;
|
||||
}
|
||||
|
||||
public void setContextPath(String contextPath) {
|
||||
|
|
|
@ -2,7 +2,8 @@ package org.xbib.netty.http.server.test;
|
|||
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import io.netty.handler.codec.http.HttpVersion;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
import org.xbib.netty.http.client.Request;
|
||||
import org.xbib.netty.http.client.listener.ResponseListener;
|
||||
|
@ -18,18 +19,19 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class CleartextHttp1Test extends TestBase {
|
||||
@ExtendWith(NettyHttpExtension.class)
|
||||
class CleartextHttp1Test {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CleartextHttp1Test.class.getName());
|
||||
|
||||
@Test
|
||||
public void testSimpleClearTextHttp1() throws Exception {
|
||||
void testSimpleClearTextHttp1() throws Exception {
|
||||
HttpAddress httpAddress = HttpAddress.http1("localhost", 8008);
|
||||
Server server = Server.builder()
|
||||
.bind(httpAddress).build();
|
||||
server.getDefaultVirtualServer().addContext("/", (request, response) ->
|
||||
server.getDefaultVirtualServer().addHandler("/", (request, response) ->
|
||||
response.write(HttpResponseStatus.OK, "text/plain", request.getRequest().content().retain()));
|
||||
server.accept();
|
||||
Client client = Client.builder()
|
||||
|
@ -51,23 +53,20 @@ public class CleartextHttp1Test extends TestBase {
|
|||
client.shutdownGracefully();
|
||||
server.shutdownGracefully();
|
||||
}
|
||||
logger.log(Level.INFO, "exepecting=1 counter=" + counter.get());
|
||||
assertEquals(1, counter.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPooledClearTextHttp1() throws Exception {
|
||||
void testPooledClearTextHttp1() throws Exception {
|
||||
int loop = 4096;
|
||||
HttpAddress httpAddress = HttpAddress.http1("localhost", 8008);
|
||||
Server server = Server.builder()
|
||||
//.enableDebug()
|
||||
.bind(httpAddress).build();
|
||||
server.getDefaultVirtualServer().addContext("/", (request, response) -> {
|
||||
server.getDefaultVirtualServer().addHandler("/", (request, response) -> {
|
||||
response.write(HttpResponseStatus.OK, "text/plain", request.getRequest().content().retain());
|
||||
});
|
||||
server.accept();
|
||||
Client client = Client.builder()
|
||||
//.enableDebug()
|
||||
.addPoolNode(httpAddress)
|
||||
.setPoolNodeConnectionLimit(2)
|
||||
.build();
|
||||
|
@ -96,19 +95,17 @@ public class CleartextHttp1Test extends TestBase {
|
|||
client.shutdownGracefully();
|
||||
server.shutdownGracefully();
|
||||
}
|
||||
logger.log(Level.INFO, "expecting=" + loop + " counter=" + counter.get());
|
||||
assertEquals(loop, counter.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultithreadedPooledClearTextHttp1() throws Exception {
|
||||
void testMultithreadedPooledClearTextHttp1() throws Exception {
|
||||
int threads = 4;
|
||||
int loop = 4 * 1024;
|
||||
HttpAddress httpAddress = HttpAddress.http1("localhost", 8008);
|
||||
Server server = Server.builder()
|
||||
//.enableDebug()
|
||||
.bind(httpAddress).build();
|
||||
server.getDefaultVirtualServer().addContext("/", (request, response) -> {
|
||||
server.getDefaultVirtualServer().addHandler("/", (request, response) -> {
|
||||
response.write(HttpResponseStatus.OK, "text/plain", request.getRequest().content().retain());
|
||||
});
|
||||
server.accept();
|
||||
|
@ -159,7 +156,6 @@ public class CleartextHttp1Test extends TestBase {
|
|||
client.shutdownGracefully();
|
||||
server.shutdownGracefully();
|
||||
}
|
||||
logger.log(Level.INFO, "expecting=" + (threads * loop) + " counter=" + counter.get());
|
||||
assertEquals(threads * loop, counter.get());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package org.xbib.netty.http.server.test;
|
||||
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
import org.xbib.netty.http.client.Request;
|
||||
import org.xbib.netty.http.client.listener.ResponseListener;
|
||||
|
@ -18,19 +19,20 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class CleartextHttp2Test extends TestBase {
|
||||
@ExtendWith(NettyHttpExtension.class)
|
||||
class CleartextHttp2Test {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CleartextHttp2Test.class.getName());
|
||||
|
||||
@Test
|
||||
public void testSimpleCleartextHttp2() throws Exception {
|
||||
void testSimpleCleartextHttp2() throws Exception {
|
||||
HttpAddress httpAddress = HttpAddress.http2("localhost", 8008);
|
||||
Server server = Server.builder()
|
||||
.bind(httpAddress)
|
||||
.build();
|
||||
server.getDefaultVirtualServer().addContext("/", (request, response) ->
|
||||
server.getDefaultVirtualServer().addHandler("/", (request, response) ->
|
||||
response.write(HttpResponseStatus.OK, "text/plain", request.getRequest().content().retain()));
|
||||
server.accept();
|
||||
Client client = Client.builder()
|
||||
|
@ -60,23 +62,19 @@ public class CleartextHttp2Test extends TestBase {
|
|||
client.shutdownGracefully();
|
||||
server.shutdownGracefully();
|
||||
}
|
||||
logger.log(Level.INFO, "counter = " + counter.get());
|
||||
assertEquals(1, counter.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPooledClearTextHttp2() throws Exception {
|
||||
void testPooledClearTextHttp2() throws Exception {
|
||||
int loop = 4096;
|
||||
HttpAddress httpAddress = HttpAddress.http2("localhost", 8008);
|
||||
Server server = Server.builder()
|
||||
.bind(httpAddress).build();
|
||||
server.getDefaultVirtualServer().addContext("/", (request, response) ->
|
||||
server.getDefaultVirtualServer().addHandler("/", (request, response) ->
|
||||
response.write(HttpResponseStatus.OK, "text/plain", request.getRequest().content().retain()));
|
||||
//server.getDefaultVirtualServer().addContext("/", (request, response) ->
|
||||
// response.write(request.getRequest().content().toString(StandardCharsets.UTF_8)));
|
||||
server.accept();
|
||||
Client client = Client.builder()
|
||||
//.enableDebug()
|
||||
.addPoolNode(httpAddress)
|
||||
.setPoolNodeConnectionLimit(2)
|
||||
.build();
|
||||
|
@ -114,14 +112,14 @@ public class CleartextHttp2Test extends TestBase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testMultithreadPooledClearTextHttp2() throws Exception {
|
||||
void testMultithreadPooledClearTextHttp2() throws Exception {
|
||||
int threads = 2;
|
||||
int loop = 4 * 1024;
|
||||
HttpAddress httpAddress = HttpAddress.http2("localhost", 8008);
|
||||
Server server = Server.builder()
|
||||
.bind(httpAddress)
|
||||
.build();
|
||||
server.getDefaultVirtualServer().addContext("/", (request, response) ->
|
||||
server.getDefaultVirtualServer().addHandler("/", (request, response) ->
|
||||
response.write(request.getRequest().content().toString(StandardCharsets.UTF_8))
|
||||
);
|
||||
server.accept();
|
||||
|
@ -176,7 +174,7 @@ public class CleartextHttp2Test extends TestBase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testTwoPooledClearTextHttp2() throws Exception {
|
||||
void testTwoPooledClearTextHttp2() throws Exception {
|
||||
int threads = 2;
|
||||
int loop = 4 * 1024;
|
||||
|
||||
|
@ -184,7 +182,7 @@ public class CleartextHttp2Test extends TestBase {
|
|||
AtomicInteger counter1 = new AtomicInteger();
|
||||
Server server1 = Server.builder()
|
||||
.bind(httpAddress1).build();
|
||||
server1.getDefaultVirtualServer().addContext("/", (request, response) -> {
|
||||
server1.getDefaultVirtualServer().addHandler("/", (request, response) -> {
|
||||
response.write(request.getRequest().content().toString(StandardCharsets.UTF_8));
|
||||
counter1.incrementAndGet();
|
||||
});
|
||||
|
@ -194,7 +192,7 @@ public class CleartextHttp2Test extends TestBase {
|
|||
AtomicInteger counter2 = new AtomicInteger();
|
||||
Server server2 = Server.builder()
|
||||
.bind(httpAddress2).build();
|
||||
server2.getDefaultVirtualServer().addContext("/", (request, response) -> {
|
||||
server2.getDefaultVirtualServer().addHandler("/", (request, response) -> {
|
||||
response.write(request.getRequest().content().toString(StandardCharsets.UTF_8));
|
||||
counter2.incrementAndGet();
|
||||
});
|
||||
|
@ -240,9 +238,9 @@ public class CleartextHttp2Test extends TestBase {
|
|||
});
|
||||
}
|
||||
executorService.shutdown();
|
||||
boolean terminated = executorService.awaitTermination(30, TimeUnit.SECONDS);
|
||||
boolean terminated = executorService.awaitTermination(60, TimeUnit.SECONDS);
|
||||
logger.log(Level.INFO, "terminated = " + terminated + ", now waiting for transport to complete");
|
||||
transport.get(30, TimeUnit.SECONDS);
|
||||
transport.get(60, TimeUnit.SECONDS);
|
||||
} finally {
|
||||
client.shutdownGracefully();
|
||||
server1.shutdownGracefully();
|
||||
|
@ -250,6 +248,6 @@ public class CleartextHttp2Test extends TestBase {
|
|||
}
|
||||
logger.log(Level.INFO, "counter1=" + counter1.get() + " counter2=" + counter2.get());
|
||||
logger.log(Level.INFO, "expecting=" + threads * loop + " counter=" + counter.get());
|
||||
//assertEquals(threads * loop, counter.get());
|
||||
assertEquals(threads * loop, counter.get());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
package org.xbib;
|
||||
package org.xbib.netty.http.server.test;
|
||||
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.junit.jupiter.api.extension.BeforeAllCallback;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
|
||||
import java.security.Security;
|
||||
import java.util.logging.ConsoleHandler;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
|
@ -7,9 +12,13 @@ import java.util.logging.LogManager;
|
|||
import java.util.logging.Logger;
|
||||
import java.util.logging.SimpleFormatter;
|
||||
|
||||
public class TestBase {
|
||||
public class NettyHttpExtension implements BeforeAllCallback {
|
||||
|
||||
static {
|
||||
@Override
|
||||
public void beforeAll(ExtensionContext context) {
|
||||
if (Security.getProvider("BC") == null) {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
System.setProperty("io.netty.noUnsafe", Boolean.toString(true));
|
||||
System.setProperty("io.netty.noKeySetOptimization", Boolean.toString(true));
|
||||
//System.setProperty("io.netty.recycler.maxCapacity", Integer.toString(0));
|
|
@ -2,8 +2,8 @@ package org.xbib.netty.http.server.test;
|
|||
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import io.netty.handler.codec.http.HttpVersion;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
import org.xbib.netty.http.client.Request;
|
||||
import org.xbib.netty.http.client.listener.ResponseListener;
|
||||
|
@ -13,7 +13,6 @@ import org.xbib.netty.http.server.Server;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.Security;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -21,20 +20,15 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class SecureHttp1Test extends TestBase {
|
||||
@ExtendWith(NettyHttpExtension.class)
|
||||
class SecureHttp1Test {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(SecureHttp1Test.class.getName());
|
||||
|
||||
static {
|
||||
if (Security.getProvider("BC") == null) {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleSecureHttp1() throws Exception {
|
||||
void testSimpleSecureHttp1() throws Exception {
|
||||
Server server = Server.builder()
|
||||
.setJdkSslProvider()
|
||||
.setSelfCert()
|
||||
|
@ -51,7 +45,7 @@ public class SecureHttp1Test extends TestBase {
|
|||
counter.getAndIncrement();
|
||||
};
|
||||
try {
|
||||
server.getDefaultVirtualServer().addContext("/", (request, response) ->
|
||||
server.getDefaultVirtualServer().addHandler("/", (request, response) ->
|
||||
response.write(HttpResponseStatus.OK, "text/plain", request.getRequest().content().retain()));
|
||||
server.accept();
|
||||
Request request = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
|
@ -63,19 +57,18 @@ public class SecureHttp1Test extends TestBase {
|
|||
client.shutdownGracefully();
|
||||
server.shutdownGracefully();
|
||||
}
|
||||
logger.log(Level.INFO, "counter=" + counter.get());
|
||||
assertEquals(1, counter.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPooledSecureHttp1() throws Exception {
|
||||
void testPooledSecureHttp1() throws Exception {
|
||||
int loop = 4096;
|
||||
HttpAddress httpAddress = HttpAddress.secureHttp1("localhost", 8143);
|
||||
Server server = Server.builder()
|
||||
.setJdkSslProvider()
|
||||
.setSelfCert()
|
||||
.bind(httpAddress).build();
|
||||
server.getDefaultVirtualServer().addContext("/", (request, response) ->
|
||||
server.getDefaultVirtualServer().addHandler("/", (request, response) ->
|
||||
response.write(HttpResponseStatus.OK, "text/plain", request.getRequest().content().retain()));
|
||||
server.accept();
|
||||
Client client = Client.builder()
|
||||
|
@ -114,7 +107,7 @@ public class SecureHttp1Test extends TestBase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testMultithreadPooledSecureHttp1() throws Exception {
|
||||
void testMultithreadPooledSecureHttp1() throws Exception {
|
||||
int threads = 4;
|
||||
int loop = 4 * 1024;
|
||||
HttpAddress httpAddress = HttpAddress.secureHttp1("localhost", 8143);
|
||||
|
@ -123,7 +116,7 @@ public class SecureHttp1Test extends TestBase {
|
|||
.setSelfCert()
|
||||
.bind(httpAddress)
|
||||
.build();
|
||||
server.getDefaultVirtualServer().addContext("/", (request, response) ->
|
||||
server.getDefaultVirtualServer().addHandler("/", (request, response) ->
|
||||
response.write(HttpResponseStatus.OK, "text/plain", request.getRequest().content().retain())
|
||||
);
|
||||
server.accept();
|
||||
|
@ -147,7 +140,7 @@ public class SecureHttp1Test extends TestBase {
|
|||
executorService.submit(() -> {
|
||||
try {
|
||||
for (int i = 0; i < loop; i++) {
|
||||
String payload = Integer.toString(t) + "/" + Integer.toString(i);
|
||||
String payload = t + "/" + i;
|
||||
Request request = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base())
|
||||
.content(payload, "text/plain")
|
||||
|
@ -168,13 +161,12 @@ public class SecureHttp1Test extends TestBase {
|
|||
});
|
||||
}
|
||||
executorService.shutdown();
|
||||
boolean terminated = executorService.awaitTermination(30, TimeUnit.SECONDS);
|
||||
boolean terminated = executorService.awaitTermination(60, TimeUnit.SECONDS);
|
||||
logger.log(Level.INFO, "terminated = " + terminated);
|
||||
} finally {
|
||||
client.shutdownGracefully();
|
||||
server.shutdownGracefully();
|
||||
}
|
||||
logger.log(Level.INFO, "expecting=" + (threads * loop) + " counter=" + counter.get());
|
||||
assertEquals(threads * loop , counter.get());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package org.xbib.netty.http.server.test;
|
||||
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
import org.xbib.netty.http.client.Request;
|
||||
import org.xbib.netty.http.client.listener.ResponseListener;
|
||||
|
@ -12,7 +12,6 @@ import org.xbib.netty.http.server.Server;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.Security;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -20,27 +19,22 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class SecureHttp2Test extends TestBase {
|
||||
@ExtendWith(NettyHttpExtension.class)
|
||||
class SecureHttp2Test {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(SecureHttp2Test.class.getName());
|
||||
|
||||
static {
|
||||
if (Security.getProvider("BC") == null) {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleSecureHttp2() throws Exception {
|
||||
void testSimpleSecureHttp2() throws Exception {
|
||||
HttpAddress httpAddress = HttpAddress.secureHttp2("localhost", 8143);
|
||||
Server server = Server.builder()
|
||||
.setJdkSslProvider()
|
||||
.setSelfCert()
|
||||
.bind(httpAddress)
|
||||
.build();
|
||||
server.getDefaultVirtualServer().addContext("/", (request, response) ->
|
||||
server.getDefaultVirtualServer().addHandler("/", (request, response) ->
|
||||
response.write(HttpResponseStatus.OK, "text/plain", request.getRequest().content().retain()));
|
||||
server.accept();
|
||||
Client client = Client.builder()
|
||||
|
@ -57,7 +51,7 @@ public class SecureHttp2Test extends TestBase {
|
|||
};
|
||||
try {
|
||||
Transport transport = client.newTransport(httpAddress);
|
||||
String payload = Integer.toString(0) + "/" + Integer.toString(0);
|
||||
String payload = 0 + "/" + 0;
|
||||
Request request = Request.get()
|
||||
.setVersion("HTTP/2.0")
|
||||
.uri("/")
|
||||
|
@ -71,12 +65,11 @@ public class SecureHttp2Test extends TestBase {
|
|||
client.shutdownGracefully();
|
||||
server.shutdownGracefully();
|
||||
}
|
||||
logger.log(Level.INFO, "counter = " + counter.get());
|
||||
assertEquals(1, counter.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPooledSecureHttp2() throws Exception {
|
||||
void testPooledSecureHttp2() throws Exception {
|
||||
int loop = 4096;
|
||||
HttpAddress httpAddress = HttpAddress.secureHttp2("localhost", 8143);
|
||||
Server server = Server.builder()
|
||||
|
@ -84,7 +77,7 @@ public class SecureHttp2Test extends TestBase {
|
|||
.setSelfCert()
|
||||
.bind(httpAddress)
|
||||
.build();
|
||||
server.getDefaultVirtualServer().addContext("/", (request, response) ->
|
||||
server.getDefaultVirtualServer().addHandler("/", (request, response) ->
|
||||
response.write(HttpResponseStatus.OK, "text/plain", request.getRequest().content().retain()));
|
||||
server.accept();
|
||||
Client client = Client.builder()
|
||||
|
@ -122,12 +115,11 @@ public class SecureHttp2Test extends TestBase {
|
|||
client.shutdownGracefully();
|
||||
server.shutdownGracefully();
|
||||
}
|
||||
logger.log(Level.INFO, "counter=" + counter.get());
|
||||
assertEquals(loop, counter.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultithreadPooledSecureHttp2() throws Exception {
|
||||
void testMultithreadPooledSecureHttp2() throws Exception {
|
||||
int threads = 4;
|
||||
int loop = 4 * 1024;
|
||||
HttpAddress httpAddress = HttpAddress.secureHttp2("localhost", 8143);
|
||||
|
@ -136,7 +128,7 @@ public class SecureHttp2Test extends TestBase {
|
|||
.setSelfCert()
|
||||
.bind(httpAddress)
|
||||
.build();
|
||||
server.getDefaultVirtualServer().addContext("/", (request, response) ->
|
||||
server.getDefaultVirtualServer().addHandler("/", (request, response) ->
|
||||
response.write(HttpResponseStatus.OK, "text/plain", request.getRequest().content().retain())
|
||||
);
|
||||
server.accept();
|
||||
|
@ -163,7 +155,7 @@ public class SecureHttp2Test extends TestBase {
|
|||
executorService.submit(() -> {
|
||||
try {
|
||||
for (int i = 0; i < loop; i++) {
|
||||
String payload = Integer.toString(t) + "/" + Integer.toString(i);
|
||||
String payload = t + "/" + i;
|
||||
Request request = Request.get().setVersion("HTTP/2.0")
|
||||
.url(server.getServerConfig().getAddress().base())
|
||||
.content(payload, "text/plain")
|
||||
|
@ -181,14 +173,13 @@ public class SecureHttp2Test extends TestBase {
|
|||
});
|
||||
}
|
||||
executorService.shutdown();
|
||||
boolean terminated = executorService.awaitTermination(30, TimeUnit.SECONDS);
|
||||
boolean terminated = executorService.awaitTermination(60, TimeUnit.SECONDS);
|
||||
logger.log(Level.INFO, "terminated = " + terminated + ", now waiting for transport to complete");
|
||||
transport.get(30, TimeUnit.SECONDS);
|
||||
transport.get(60, TimeUnit.SECONDS);
|
||||
} finally {
|
||||
client.shutdownGracefully();
|
||||
server.shutdownGracefully();
|
||||
}
|
||||
logger.log(Level.INFO, "expected=" + (threads * loop) + " counter=" + counter.get());
|
||||
assertEquals(threads * loop , counter.get());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
package org.xbib.netty.http.server.test;
|
||||
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.xbib.netty.http.server.security.tls.SelfSignedCertificate;
|
||||
|
||||
import java.security.Security;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class SelfSignedCertificateTest {
|
||||
class SelfSignedCertificateTest {
|
||||
|
||||
@Test
|
||||
public void testSelfSignedCertificate() throws Exception {
|
||||
void testSelfSignedCertificate() throws Exception {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
SelfSignedCertificate selfSignedCertificate = new SelfSignedCertificate("localhost");
|
||||
selfSignedCertificate.exportPEM(Logger.getLogger("test"));
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
package org.xbib.netty.http.server.test;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.xbib.netty.http.server.Server;
|
||||
|
||||
@Ignore
|
||||
public class ServerTest {
|
||||
@Disabled
|
||||
class ServerTest {
|
||||
|
||||
@Test
|
||||
public void testServer() throws Exception {
|
||||
void testServer() throws Exception {
|
||||
Server server = Server.builder()
|
||||
.build();
|
||||
server.getDefaultVirtualServer().addContext("/", (request, response) ->
|
||||
server.getDefaultVirtualServer().addHandler("/", (request, response) ->
|
||||
response.write("Hello World"));
|
||||
try {
|
||||
server.accept().channel().closeFuture().sync();
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package org.xbib.netty.http.server.test;
|
||||
|
||||
import io.netty.handler.codec.http.HttpVersion;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
import org.xbib.netty.http.client.Request;
|
||||
import org.xbib.netty.http.common.HttpAddress;
|
||||
import org.xbib.netty.http.server.Server;
|
||||
import org.xbib.netty.http.server.context.NioContextHandler;
|
||||
import org.xbib.netty.http.server.context.VirtualServer;
|
||||
import org.xbib.netty.http.server.endpoint.NioHandler;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
|
@ -16,18 +16,19 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class StaticFileServerTest {
|
||||
class StaticFileServerTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(StaticFileServerTest.class.getName());
|
||||
|
||||
@Test
|
||||
public void testStaticFileServer() throws Exception {
|
||||
void testStaticFileServer() throws Exception {
|
||||
Path vartmp = Paths.get("/var/tmp/");
|
||||
Server server = Server.builder()
|
||||
.addVirtualServer(new VirtualServer().addContext("/static", new NioContextHandler(vartmp)))
|
||||
.bind(HttpAddress.http1("localhost", 8008))
|
||||
.addHandler("/static", new NioHandler(vartmp))
|
||||
.build();
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package org.xbib.netty.http.server.test;
|
||||
|
||||
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.server.Server;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -10,16 +12,18 @@ import java.util.Set;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class ThreadLeakTest extends TestBase {
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
@ExtendWith(NettyHttpExtension.class)
|
||||
class ThreadLeakTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ThreadLeakTest.class.getName());
|
||||
|
||||
@Test
|
||||
public void testForLeaks() throws IOException {
|
||||
void testForLeaks() throws IOException {
|
||||
Server server = Server.builder()
|
||||
.setByteBufAllocator(UnpooledByteBufAllocator.DEFAULT)
|
||||
.build();
|
||||
server.getDefaultVirtualServer().addContext("/", (request, response) ->
|
||||
server.getDefaultVirtualServer().addHandler("/", (request, response) ->
|
||||
response.write("Hello World"));
|
||||
try {
|
||||
server.accept();
|
||||
|
@ -28,8 +32,8 @@ public class ThreadLeakTest extends TestBase {
|
|||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void checkThreads() throws Exception {
|
||||
@AfterAll
|
||||
void checkThreads() throws Exception {
|
||||
Thread.sleep(1000L);
|
||||
System.gc();
|
||||
Thread.sleep(3000L);
|
||||
|
|
|
@ -29,9 +29,9 @@ import io.netty.handler.codec.http2.HttpToHttp2ConnectionHandlerBuilder;
|
|||
import io.netty.handler.codec.http2.InboundHttp2ToHttpAdapterBuilder;
|
||||
import io.netty.handler.logging.LogLevel;
|
||||
import io.netty.handler.logging.LoggingHandler;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.xbib.netty.http.server.test.TestBase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.server.test.NettyHttpExtension;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
@ -39,8 +39,8 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Ignore
|
||||
public class CleartextHttp2Test extends TestBase {
|
||||
@ExtendWith(NettyHttpExtension.class)
|
||||
class CleartextHttp2Test {
|
||||
|
||||
private static final Logger clientLogger = Logger.getLogger("client");
|
||||
private static final Logger serverLogger = Logger.getLogger("server");
|
||||
|
@ -56,17 +56,12 @@ public class CleartextHttp2Test extends TestBase {
|
|||
private CompletableFuture<Boolean> completableFuture;
|
||||
|
||||
@Test
|
||||
public void testHttp2() throws Exception {
|
||||
|
||||
void testHttp2() throws Exception {
|
||||
final InetSocketAddress inetSocketAddress = new InetSocketAddress("localhost", 8008);
|
||||
|
||||
settingsPrefaceFuture = new CompletableFuture<>();
|
||||
|
||||
completableFuture = new CompletableFuture<>();
|
||||
|
||||
EventLoopGroup serverEventLoopGroup = new NioEventLoopGroup();
|
||||
EventLoopGroup clientEventLoopGroup = new NioEventLoopGroup();
|
||||
|
||||
try {
|
||||
Http2Connection http2ServerConnection = new DefaultHttp2Connection(true);
|
||||
ServerBootstrap serverBootstrap = new ServerBootstrap()
|
||||
|
@ -132,7 +127,7 @@ public class CleartextHttp2Test extends TestBase {
|
|||
clientChannel.writeAndFlush(request);
|
||||
|
||||
clientLogger.log(level, "waiting");
|
||||
completableFuture.get(10, TimeUnit.SECONDS);
|
||||
completableFuture.get(30, TimeUnit.SECONDS);
|
||||
if (completableFuture.isDone()) {
|
||||
clientLogger.log(Level.INFO, "done");
|
||||
}
|
||||
|
|
|
@ -18,13 +18,15 @@ import io.netty.handler.codec.http.HttpResponseStatus;
|
|||
import io.netty.handler.codec.http.HttpVersion;
|
||||
import io.netty.handler.codec.http.LastHttpContent;
|
||||
import io.netty.handler.codec.http.QueryStringDecoder;
|
||||
import org.junit.After;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.server.handler.http.HttpPipelinedRequest;
|
||||
import org.xbib.netty.http.server.handler.http.HttpPipelinedResponse;
|
||||
import org.xbib.netty.http.server.handler.http.HttpPipeliningHandler;
|
||||
import org.xbib.netty.http.server.test.TestBase;
|
||||
import org.xbib.netty.http.server.test.NettyHttpExtension;
|
||||
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -42,26 +44,30 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@Ignore
|
||||
public class HttpPipeliningHandlerTest extends TestBase {
|
||||
/** flaky */
|
||||
@Disabled
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
@ExtendWith(NettyHttpExtension.class)
|
||||
class HttpPipeliningHandlerTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(HttpPipeliningHandlerTest.class.getName());
|
||||
|
||||
private static Map<String, CountDownLatch> waitingRequests = new ConcurrentHashMap<>();
|
||||
|
||||
@After
|
||||
public void closeResources() {
|
||||
@AfterAll
|
||||
void closeResources() {
|
||||
for (String url : waitingRequests.keySet()) {
|
||||
finishRequest(url);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatPipeliningWorksWithFastSerializedRequests() {
|
||||
void testThatPipeliningWorksWithFastSerializedRequests() {
|
||||
WorkEmulatorHandler handler = new WorkEmulatorHandler();
|
||||
EmbeddedChannel embeddedChannel = new EmbeddedChannel(new HttpPipeliningHandler(10000),
|
||||
handler);
|
||||
|
@ -75,11 +81,11 @@ public class HttpPipeliningHandlerTest extends TestBase {
|
|||
for (int i = 0; i < 5; i++) {
|
||||
assertReadHttpMessageHasContent(embeddedChannel, String.valueOf(i));
|
||||
}
|
||||
assertThat(embeddedChannel.isOpen(), is(true));
|
||||
assertTrue(embeddedChannel.isOpen());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatPipeliningWorksWhenSlowRequestsInDifferentOrder() {
|
||||
void testThatPipeliningWorksWhenSlowRequestsInDifferentOrder() {
|
||||
WorkEmulatorHandler handler = new WorkEmulatorHandler();
|
||||
EmbeddedChannel embeddedChannel = new EmbeddedChannel(new HttpPipeliningHandler(10000),
|
||||
handler);
|
||||
|
@ -95,11 +101,11 @@ public class HttpPipeliningHandlerTest extends TestBase {
|
|||
for (int i = 0; i < 5; i++) {
|
||||
assertReadHttpMessageHasContent(embeddedChannel, String.valueOf(i));
|
||||
}
|
||||
assertThat(embeddedChannel.isOpen(), is(true));
|
||||
assertTrue(embeddedChannel.isOpen());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatPipeliningWorksWithChunkedRequests() {
|
||||
void testThatPipeliningWorksWithChunkedRequests() {
|
||||
WorkEmulatorHandler handler = new WorkEmulatorHandler();
|
||||
EmbeddedChannel embeddedChannel = new EmbeddedChannel(new AggregateUrisAndHeadersHandler(),
|
||||
new HttpPipeliningHandler(10000), handler);
|
||||
|
@ -115,11 +121,12 @@ public class HttpPipeliningHandlerTest extends TestBase {
|
|||
for (int i = 0; i < 2; i++) {
|
||||
assertReadHttpMessageHasContent(embeddedChannel, String.valueOf(i));
|
||||
}
|
||||
assertThat(embeddedChannel.isOpen(), is(true));
|
||||
assertTrue(embeddedChannel.isOpen());
|
||||
}
|
||||
|
||||
@Test(expected = ClosedChannelException.class)
|
||||
public void testThatPipeliningClosesConnectionWithTooManyEvents() {
|
||||
@Test
|
||||
void testThatPipeliningClosesConnectionWithTooManyEvents() {
|
||||
assertThrows(ClosedChannelException.class, () -> {
|
||||
WorkEmulatorHandler handler = new WorkEmulatorHandler();
|
||||
EmbeddedChannel embeddedChannel = new EmbeddedChannel(new HttpPipeliningHandler(2),
|
||||
handler);
|
||||
|
@ -133,14 +140,15 @@ public class HttpPipeliningHandlerTest extends TestBase {
|
|||
finishRequest("0");
|
||||
handler.shutdownExecutorService();
|
||||
embeddedChannel.writeInbound(createHttpRequest("/"));
|
||||
});
|
||||
}
|
||||
|
||||
private void assertReadHttpMessageHasContent(EmbeddedChannel embeddedChannel, String expectedContent) {
|
||||
FullHttpResponse response = (FullHttpResponse) embeddedChannel.outboundMessages().poll();
|
||||
assertNotNull("Expected response to exist, maybe you did not wait long enough?", response);
|
||||
assertNotNull("Expected response to have content " + expectedContent, response.content());
|
||||
assertNotNull(response);
|
||||
assertNotNull(response.content());
|
||||
String data = new String(ByteBufUtil.getBytes(response.content()), StandardCharsets.UTF_8);
|
||||
assertThat(data, is(expectedContent));
|
||||
assertEquals(expectedContent, data);
|
||||
}
|
||||
|
||||
private void finishRequest(String url) {
|
||||
|
@ -163,7 +171,7 @@ public class HttpPipeliningHandlerTest extends TestBase {
|
|||
|
||||
private class WorkEmulatorHandler extends SimpleChannelInboundHandler<HttpPipelinedRequest> {
|
||||
|
||||
private final ExecutorService executorService = Executors.newFixedThreadPool(5);
|
||||
private final ExecutorService executorService = Executors.newFixedThreadPool(8);
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, HttpPipelinedRequest pipelinedRequest) {
|
||||
|
@ -181,6 +189,7 @@ public class HttpPipeliningHandlerTest extends TestBase {
|
|||
httpResponse.headers().add(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
waitingRequests.put(uri, latch);
|
||||
// can cause RejectedExecutionException if executorService is too small
|
||||
executorService.submit(() -> {
|
||||
try {
|
||||
latch.await(2, TimeUnit.SECONDS);
|
||||
|
|
|
@ -25,7 +25,6 @@ import io.netty.handler.codec.http.HttpServerUpgradeHandler;
|
|||
import io.netty.handler.codec.http.HttpVersion;
|
||||
import io.netty.handler.codec.http2.CleartextHttp2ServerUpgradeHandler;
|
||||
import io.netty.handler.codec.http2.DefaultHttp2Headers;
|
||||
//import io.netty.handler.codec.http2.DefaultHttp2PushPromiseFrame;
|
||||
import io.netty.handler.codec.http2.DefaultHttp2HeadersFrame;
|
||||
import io.netty.handler.codec.http2.Http2CodecUtil;
|
||||
import io.netty.handler.codec.http2.Http2ConnectionPrefaceAndSettingsFrameWrittenEvent;
|
||||
|
@ -41,9 +40,9 @@ import io.netty.handler.codec.http2.Http2StreamFrameToHttpObjectCodec;
|
|||
import io.netty.handler.logging.LogLevel;
|
||||
import io.netty.handler.logging.LoggingHandler;
|
||||
import io.netty.util.AsciiString;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.xbib.netty.http.server.test.TestBase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.server.test.NettyHttpExtension;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
@ -69,8 +68,8 @@ import java.util.logging.Logger;
|
|||
*
|
||||
*
|
||||
*/
|
||||
@Ignore
|
||||
public class MultiplexCodecCleartextHttp2Test extends TestBase {
|
||||
@ExtendWith(NettyHttpExtension.class)
|
||||
class MultiplexCodecCleartextHttp2Test {
|
||||
|
||||
private static final Logger clientLogger = Logger.getLogger("client");
|
||||
private static final Logger serverLogger = Logger.getLogger("server");
|
||||
|
@ -82,14 +81,11 @@ public class MultiplexCodecCleartextHttp2Test extends TestBase {
|
|||
private final CompletableFuture<Boolean> responseFuture = new CompletableFuture<>();
|
||||
|
||||
@Test
|
||||
public void testMultiplexHttp2() throws Exception {
|
||||
|
||||
void testMultiplexHttp2() throws Exception {
|
||||
Http2FrameLogger serverFrameLogger = new Http2FrameLogger(LogLevel.INFO, "server");
|
||||
Http2FrameLogger clientFrameLogger = new Http2FrameLogger(LogLevel.INFO, "client");
|
||||
|
||||
EventLoopGroup serverEventLoopGroup = new NioEventLoopGroup();
|
||||
EventLoopGroup clientEventLoopGroup = new NioEventLoopGroup();
|
||||
|
||||
try {
|
||||
ServerBootstrap serverBootstrap = new ServerBootstrap()
|
||||
.group(serverEventLoopGroup)
|
||||
|
|
|
@ -27,9 +27,9 @@ import io.netty.handler.codec.http2.Http2ConnectionPrefaceAndSettingsFrameWritte
|
|||
import io.netty.handler.codec.http2.Http2Settings;
|
||||
import io.netty.handler.codec.http2.HttpToHttp2ConnectionHandlerBuilder;
|
||||
import io.netty.handler.codec.http2.InboundHttp2ToHttpAdapterBuilder;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.xbib.netty.http.server.test.TestBase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.server.test.NettyHttpExtension;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
@ -40,8 +40,8 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Ignore
|
||||
public class MultithreadedCleartextHttp2Test extends TestBase {
|
||||
@ExtendWith(NettyHttpExtension.class)
|
||||
class MultithreadedCleartextHttp2Test {
|
||||
|
||||
private static final Logger clientLogger = Logger.getLogger("client");
|
||||
private static final Logger serverLogger = Logger.getLogger("server");
|
||||
|
@ -61,7 +61,7 @@ public class MultithreadedCleartextHttp2Test extends TestBase {
|
|||
private final AtomicInteger responseCounter = new AtomicInteger();
|
||||
|
||||
@Test
|
||||
public void testMultiThreadedHttp2() throws Exception {
|
||||
void testMultiThreadedHttp2() throws Exception {
|
||||
|
||||
inetSocketAddress = new InetSocketAddress("localhost", 8008);
|
||||
settingsPrefaceFuture = new CompletableFuture<>();
|
||||
|
|
|
@ -35,9 +35,9 @@ import io.netty.handler.codec.http2.Http2StreamChannel;
|
|||
import io.netty.handler.codec.http2.Http2StreamChannelBootstrap;
|
||||
import io.netty.handler.codec.http2.Http2StreamFrameToHttpObjectCodec;
|
||||
import io.netty.util.AsciiString;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.xbib.netty.http.server.test.TestBase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.server.test.NettyHttpExtension;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
@ -53,8 +53,8 @@ import java.util.logging.Logger;
|
|||
* Multithreaded Http2MultiplexCodec demo for cleartext HTTP/2 between a server and a client.
|
||||
*
|
||||
*/
|
||||
@Ignore
|
||||
public class MultithreadedMultiplexCodecCleartextHttp2Test extends TestBase {
|
||||
@ExtendWith(NettyHttpExtension.class)
|
||||
class MultithreadedMultiplexCodecCleartextHttp2Test {
|
||||
|
||||
private static final Logger clientLogger = Logger.getLogger("client");
|
||||
private static final Logger serverLogger = Logger.getLogger("server");
|
||||
|
@ -74,7 +74,7 @@ public class MultithreadedMultiplexCodecCleartextHttp2Test extends TestBase {
|
|||
private final AtomicInteger responseCounter = new AtomicInteger();
|
||||
|
||||
@Test
|
||||
public void testMultithreadedMultiplexHttp2() throws Exception {
|
||||
void testMultithreadedMultiplexHttp2() throws Exception {
|
||||
|
||||
inetSocketAddress = new InetSocketAddress("localhost", 8008);
|
||||
settingsPrefaceFuture = new CompletableFuture<>();
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
include 'netty-http-common'
|
||||
include 'netty-http-client'
|
||||
include 'netty-http-server'
|
||||
include 'netty-http-server-rest'
|
Loading…
Reference in a new issue