diff --git a/bom/application/pom.xml b/bom/application/pom.xml
index fadad60a12689..b2afc0d2087e8 100644
--- a/bom/application/pom.xml
+++ b/bom/application/pom.xml
@@ -114,7 +114,7 @@
1.15.4.Final
1.8.7.Final
3.2.0.Final
- 4.1.0.Beta1
+ 4.1.0.CR1
4.5.13
4.4.14
4.1.4
@@ -137,7 +137,7 @@
12.1.1.Final
4.4.0.Final
2.9.1
- 4.1.60.Final
+ 4.1.65.Final
1.0.3
3.4.1.Final
0.17.0
diff --git a/extensions/netty/runtime/pom.xml b/extensions/netty/runtime/pom.xml
index 880977accf3a0..78bcd224ba879 100644
--- a/extensions/netty/runtime/pom.xml
+++ b/extensions/netty/runtime/pom.xml
@@ -22,6 +22,14 @@
io.netty
netty-codec
+
+ io.netty
+ netty-codec-http
+
+
+ io.netty
+ netty-codec-http2
+
io.quarkus
quarkus-arc
diff --git a/extensions/netty/runtime/src/main/java/io/quarkus/netty/runtime/graal/NettySubstitutions.java b/extensions/netty/runtime/src/main/java/io/quarkus/netty/runtime/graal/NettySubstitutions.java
index 2580740d1b690..19b5ed2e83dd2 100644
--- a/extensions/netty/runtime/src/main/java/io/quarkus/netty/runtime/graal/NettySubstitutions.java
+++ b/extensions/netty/runtime/src/main/java/io/quarkus/netty/runtime/graal/NettySubstitutions.java
@@ -1,5 +1,10 @@
package io.quarkus.netty.runtime.graal;
+import static io.netty.handler.codec.http.HttpHeaderValues.DEFLATE;
+import static io.netty.handler.codec.http.HttpHeaderValues.GZIP;
+import static io.netty.handler.codec.http.HttpHeaderValues.X_DEFLATE;
+import static io.netty.handler.codec.http.HttpHeaderValues.X_GZIP;
+
import java.nio.ByteBuffer;
import java.security.PrivateKey;
import java.security.Provider;
@@ -17,6 +22,7 @@
import javax.net.ssl.TrustManagerFactory;
import com.oracle.svm.core.annotate.Alias;
+import com.oracle.svm.core.annotate.Delete;
import com.oracle.svm.core.annotate.RecomputeFieldValue;
import com.oracle.svm.core.annotate.RecomputeFieldValue.Kind;
import com.oracle.svm.core.annotate.Substitute;
@@ -29,7 +35,14 @@
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.DefaultChannelPromise;
+import io.netty.channel.embedded.EmbeddedChannel;
+import io.netty.handler.codec.compression.ZlibCodecFactory;
+import io.netty.handler.codec.compression.ZlibWrapper;
+import io.netty.handler.codec.http.HttpHeaderValues;
+import io.netty.handler.codec.http2.Http2Exception;
import io.netty.handler.ssl.ApplicationProtocolConfig;
import io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior;
import io.netty.handler.ssl.CipherSuiteFilter;
@@ -83,7 +96,9 @@ static boolean isAlpnSupported() {
}
}
-/** Hardcode io.netty.handler.ssl.OpenSsl as non-available */
+/**
+ * Hardcode io.netty.handler.ssl.OpenSsl as non-available
+ */
@TargetClass(className = "io.netty.handler.ssl.OpenSsl")
final class Target_io_netty_handler_ssl_OpenSsl {
@@ -186,7 +201,8 @@ final class Target_io_netty_handler_ssl_JdkAlpnApplicationProtocolNegotiator_Alp
@Substitute
public SSLEngine wrapSslEngine(SSLEngine engine, ByteBufAllocator alloc,
JdkApplicationProtocolNegotiator applicationNegotiator, boolean isServer) {
- return (SSLEngine) (Object) new Target_io_netty_handler_ssl_JdkAlpnSslEngine(engine, applicationNegotiator, isServer);
+ return (SSLEngine) (Object) new Target_io_netty_handler_ssl_JdkAlpnSslEngine(engine, applicationNegotiator,
+ isServer);
}
}
@@ -242,7 +258,8 @@ final class Target_io_netty_handler_ssl_SslContext {
@Substitute
static SslContext newServerContextInternal(SslProvider provider, Provider sslContextProvider,
- X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory, X509Certificate[] keyCertChain,
+ X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
+ X509Certificate[] keyCertChain,
PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory, Iterable ciphers,
CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, long sessionCacheSize, long sessionTimeout,
ClientAuth clientAuth, String[] protocols, boolean startTls, boolean enableOcsp, String keyStoreType,
@@ -257,10 +274,12 @@ static SslContext newServerContextInternal(SslProvider provider, Provider sslCon
}
@Substitute
- static SslContext newClientContextInternal(SslProvider provider, Provider sslContextProvider, X509Certificate[] trustCert,
+ static SslContext newClientContextInternal(SslProvider provider, Provider sslContextProvider,
+ X509Certificate[] trustCert,
TrustManagerFactory trustManagerFactory, X509Certificate[] keyCertChain, PrivateKey key, String keyPassword,
KeyManagerFactory keyManagerFactory, Iterable ciphers, CipherSuiteFilter cipherFilter,
- ApplicationProtocolConfig apn, String[] protocols, long sessionCacheSize, long sessionTimeout, boolean enableOcsp,
+ ApplicationProtocolConfig apn, String[] protocols, long sessionCacheSize, long sessionTimeout,
+ boolean enableOcsp,
String keyStoreType, Map.Entry, Object>... options) throws SSLException {
if (enableOcsp) {
throw new IllegalArgumentException("OCSP is not supported with this SslProvider: " + provider);
@@ -305,11 +324,11 @@ static JdkApplicationProtocolNegotiator toNegotiator(ApplicationProtocolConfig c
// .append(config.selectorFailureBehavior()).append(" failure behavior").toString());
// }
SelectorFailureBehavior behavior = config.selectorFailureBehavior();
- if (behavior == SelectorFailureBehavior.FATAL_ALERT)
+ if (behavior == SelectorFailureBehavior.FATAL_ALERT) {
return new JdkAlpnApplicationProtocolNegotiator(true, config.supportedProtocols());
- else if (behavior == SelectorFailureBehavior.NO_ADVERTISE)
+ } else if (behavior == SelectorFailureBehavior.NO_ADVERTISE) {
return new JdkAlpnApplicationProtocolNegotiator(false, config.supportedProtocols());
- else {
+ } else {
throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ")
.append(config.selectorFailureBehavior()).append(" failure behavior").toString());
}
@@ -321,12 +340,14 @@ else if (behavior == SelectorFailureBehavior.NO_ADVERTISE)
return new JdkAlpnApplicationProtocolNegotiator(true, config.supportedProtocols());
default:
throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ")
- .append(config.selectedListenerFailureBehavior()).append(" failure behavior").toString());
+ .append(config.selectedListenerFailureBehavior()).append(" failure behavior")
+ .toString());
}
}
default:
throw new UnsupportedOperationException(
- new StringBuilder("JDK provider does not support ").append(config.protocol()).append(" protocol")
+ new StringBuilder("JDK provider does not support ").append(config.protocol())
+ .append(" protocol")
.toString());
}
}
@@ -515,6 +536,67 @@ public long memoryAddress() {
}
+@TargetClass(className = "io.netty.handler.codec.compression.BrotliDecoder")
+@Delete
+final class Target_BrotliDecoder {
+
+}
+
+@TargetClass(className = "io.netty.handler.codec.http.HttpContentDecompressor")
+final class Target_io_netty_handler_codec_http_HttpContentDecompressor {
+
+ @Alias
+ private boolean strict;
+
+ @Alias
+ protected ChannelHandlerContext ctx;
+
+ @Substitute
+ protected EmbeddedChannel newContentDecoder(String contentEncoding) throws Exception {
+ if (GZIP.contentEqualsIgnoreCase(contentEncoding) ||
+ X_GZIP.contentEqualsIgnoreCase(contentEncoding)) {
+ return new EmbeddedChannel(ctx.channel().id(), ctx.channel().metadata().hasDisconnect(),
+ ctx.channel().config(), ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP));
+ }
+ if (DEFLATE.contentEqualsIgnoreCase(contentEncoding) ||
+ X_DEFLATE.contentEqualsIgnoreCase(contentEncoding)) {
+ final ZlibWrapper wrapper = strict ? ZlibWrapper.ZLIB : ZlibWrapper.ZLIB_OR_NONE;
+ // To be strict, 'deflate' means ZLIB, but some servers were not implemented correctly.
+ return new EmbeddedChannel(ctx.channel().id(), ctx.channel().metadata().hasDisconnect(),
+ ctx.channel().config(), ZlibCodecFactory.newZlibDecoder(wrapper));
+ }
+
+ // 'identity' or unsupported
+ return null;
+ }
+}
+
+@TargetClass(className = "io.netty.handler.codec.http2.DelegatingDecompressorFrameListener")
+final class Target_io_netty_handler_codec_http2_DelegatingDecompressorFrameListener {
+
+ @Alias
+ boolean strict;
+
+ @Substitute
+ protected EmbeddedChannel newContentDecompressor(ChannelHandlerContext ctx, CharSequence contentEncoding)
+ throws Http2Exception {
+ if (!HttpHeaderValues.GZIP.contentEqualsIgnoreCase(contentEncoding)
+ && !HttpHeaderValues.X_GZIP.contentEqualsIgnoreCase(contentEncoding)) {
+ if (!HttpHeaderValues.DEFLATE.contentEqualsIgnoreCase(contentEncoding)
+ && !HttpHeaderValues.X_DEFLATE.contentEqualsIgnoreCase(contentEncoding)) {
+ return null;
+ } else {
+ ZlibWrapper wrapper = this.strict ? ZlibWrapper.ZLIB : ZlibWrapper.ZLIB_OR_NONE;
+ return new EmbeddedChannel(ctx.channel().id(), ctx.channel().metadata().hasDisconnect(), ctx.channel().config(),
+ new ChannelHandler[] { ZlibCodecFactory.newZlibDecoder(wrapper) });
+ }
+ } else {
+ return new EmbeddedChannel(ctx.channel().id(), ctx.channel().metadata().hasDisconnect(), ctx.channel().config(),
+ new ChannelHandler[] { ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP) });
+ }
+ }
+}
+
class NettySubstitutions {
}
diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/CompressionTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/CompressionTest.java
index 4384a442e9986..29ab204a67472 100644
--- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/CompressionTest.java
+++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/CompressionTest.java
@@ -1,5 +1,8 @@
package io.quarkus.vertx.http;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.nullValue;
+
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
@@ -45,7 +48,7 @@ public void test() throws Exception {
.body(Matchers.equalTo(longString));
RestAssured.given().get("/nocompress").then().statusCode(200)
- .header("content-encoding", "identity")
+ .header("content-encoding", is(nullValue()))
.header("content-length", Matchers.equalTo(Integer.toString(longString.length())))
.body(Matchers.equalTo(longString));
}
diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/hotreload/VertxInjectionTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/hotreload/VertxInjectionTest.java
index 993b549643bdf..194dbb538884c 100644
--- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/hotreload/VertxInjectionTest.java
+++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/hotreload/VertxInjectionTest.java
@@ -23,9 +23,7 @@ public void testEditingBeanUsingVertx() {
.statusCode(200)
.body(containsString("hello"));
- System.out.println("Modification");
TEST.modifySourceFile("VertxEventBusConsumer.java", s -> s.replace("hello", "bonjour"));
- System.out.println("After");
RestAssured.get("/").then()
.statusCode(200)
.body(containsString("bonjour"));
diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/filters/QuarkusRequestWrapper.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/filters/QuarkusRequestWrapper.java
index ab9210d6cdbdc..15efa520877ec 100644
--- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/filters/QuarkusRequestWrapper.java
+++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/filters/QuarkusRequestWrapper.java
@@ -204,6 +204,11 @@ public Cookie setMaxAge(long maxAge) {
return null;
}
+ @Override
+ public long getMaxAge() {
+ return Long.MIN_VALUE;
+ }
+
@Override
public Cookie setSecure(boolean secure) {
return null;