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