Repository: quarkusio/quarkus
Issue: Resteasy reactive with Http 1.1 Pipelining raising exception since quarkus 2.4.0

### Describe the bug

In a quarkus 2.7.5 app running with docker I've noticed the following errors:
```
2022-03-29 09:05:30,993 ERROR [io.qua.ver.cor.run.VertxCoreRecorder] (vert.x-eventloop-thread-1) Uncaught exception received by Vert.x: java.lang.IllegalStateException: Can't set the context safety flag: the current context is not a duplicated context
    at io.quarkus.vertx.core.runtime.context.VertxContextSafetyToggle.setContextSafe(VertxContextSafetyToggle.java:107)
    at io.quarkus.vertx.core.runtime.context.VertxContextSafetyToggle.setCurrentContextSafe(VertxContextSafetyToggle.java:94)
    at io.quarkus.vertx.http.runtime.VertxHttpRecorder$12.handle(VertxHttpRecorder.java:504)
    at io.quarkus.vertx.http.runtime.VertxHttpRecorder$12.handle(VertxHttpRecorder.java:501)
    at io.quarkus.vertx.http.runtime.VertxHttpRecorder$1.handle(VertxHttpRecorder.java:161)
    at io.quarkus.vertx.http.runtime.VertxHttpRecorder$1.handle(VertxHttpRecorder.java:143)
    at io.vertx.core.http.impl.Http1xServerRequestHandler.handle(Http1xServerRequestHandler.java:67)
    at io.vertx.core.http.impl.Http1xServerRequestHandler.handle(Http1xServerRequestHandler.java:30)
    at io.vertx.core.http.impl.Http1xServerConnection.lambda$handleNext$1(Http1xServerConnection.java:225)
    at io.vertx.core.impl.EventLoopContext.emit(EventLoopContext.java:50)
    at io.vertx.core.impl.ContextImpl.emit(ContextImpl.java:274)
    at io.vertx.core.impl.EventLoopContext.emit(EventLoopContext.java:22)
    at io.vertx.core.http.impl.Http1xServerConnection.handleNext(Http1xServerConnection.java:222)
    at io.vertx.core.http.impl.Http1xServerConnection.responseComplete(Http1xServerConnection.java:207)
    at io.vertx.core.http.impl.Http1xServerResponse.end(Http1xServerResponse.java:418)
    at io.vertx.core.http.impl.Http1xServerResponse.end(Http1xServerResponse.java:391)
    at io.quarkus.vertx.http.runtime.filters.AbstractResponseWrapper.end(AbstractResponseWrapper.java:223)
    at org.jboss.resteasy.reactive.server.vertx.ResteasyReactiveOutputStream.write(ResteasyReactiveOutputStream.java:100)
    at org.jboss.resteasy.reactive.server.vertx.ResteasyReactiveOutputStream.writeBlocking(ResteasyReactiveOutputStream.java:224)
    at org.jboss.resteasy.reactive.server.vertx.ResteasyReactiveOutputStream.close(ResteasyReactiveOutputStream.java:270)
    at io.quarkus.resteasy.reactive.jackson.runtime.serialisers.BasicServerJacksonMessageBodyWriter.writeResponse(BasicServerJacksonMessageBodyWriter.java:44)
    at org.jboss.resteasy.reactive.server.core.ServerSerialisers.invokeWriter(ServerSerialisers.java:207)
    at org.jboss.resteasy.reactive.server.core.ServerSerialisers.invokeWriter(ServerSerialisers.java:178)
    at org.jboss.resteasy.reactive.server.core.serialization.FixedEntityWriter.write(FixedEntityWriter.java:26)
    at org.jboss.resteasy.reactive.server.handlers.ResponseWriterHandler.handle(ResponseWriterHandler.java:33)
    at org.jboss.resteasy.reactive.server.handlers.ResponseWriterHandler.handle(ResponseWriterHandler.java:15)
    at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:141)
    at org.jboss.resteasy.reactive.server.vertx.VertxResteasyReactiveRequestContext$1$1.handle(VertxResteasyReactiveRequestContext.java:73)
    at org.jboss.resteasy.reactive.server.vertx.VertxResteasyReactiveRequestContext$1$1.handle(VertxResteasyReactiveRequestContext.java:70)
    at io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:100)
    at io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:63)
    at io.vertx.core.impl.EventLoopContext.lambda$runOnContext$0(EventLoopContext.java:38)
    at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:829)
```

I think this is due to the client using pipelining, I can reproduce the error running in dev mode with the simplest endpoint possible
```
package org.acme;

import io.smallrye.mutiny.Uni;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import org.jboss.logging.Logger;

@Path("/")
public class Endpoint {

  @Inject
  Logger logger;


  @GET
  public Uni<String> endpoint() {
    logger.info("Api called");
    return Uni.createFrom().item("Hello");
  }
}
```

Sending 2 requests with
```
echo -en "GET / HTTP/1.1\\r\\nHost: localhost\\r\\n\\r\\nGET / HTTP/1.1\\r\\nHost: localhost\\r\\n\\r\\n" | nc localhost 8080
```
On version 2.7.5.Final / 2.8.0.CR1 results in:
```
2022-03-30 10:25:32,902 INFO  [io.quarkus] (Quarkus Main Thread) code-with-quarkus 1.0.0-SNAPSHOT on JVM (powered by Quarkus 2.7.5.Final) started in 1.332s. Listening on: http://localhost:8080
2022-03-30 10:25:32,915 INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2022-03-30 10:25:32,916 INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, resteasy-reactive, smallrye-context-propagation, vertx]
2022-03-30 10:25:38,721 INFO  [org.acm.Endpoint] (vert.x-eventloop-thread-23) Api called
2022-03-30 10:25:38,736 ERROR [io.qua.ver.cor.run.VertxCoreRecorder] (vert.x-eventloop-thread-23) Uncaught exception received by Vert.x: java.lang.IllegalStateException: Can't set the context safety flag: the current context is not a duplicated context
    at io.quarkus.vertx.core.runtime.context.VertxContextSafetyToggle.setContextSafe(VertxContextSafetyToggle.java:107)
    at io.quarkus.vertx.core.runtime.context.VertxContextSafetyToggle.setCurrentContextSafe(VertxContextSafetyToggle.java:94)
    at io.quarkus.vertx.http.runtime.VertxHttpRecorder$12.handle(VertxHttpRecorder.java:504)
    at io.quarkus.vertx.http.runtime.VertxHttpRecorder$12.handle(VertxHttpRecorder.java:501)
    at io.quarkus.vertx.http.runtime.VertxHttpRecorder$1.handle(VertxHttpRecorder.java:161)
    at io.quarkus.vertx.http.runtime.VertxHttpRecorder$1.handle(VertxHttpRecorder.java:143)
    at io.vertx.core.http.impl.Http1xServerRequestHandler.handle(Http1xServerRequestHandler.java:67)
    at io.vertx.core.http.impl.Http1xServerRequestHandler.handle(Http1xServerRequestHandler.java:30)
    at io.vertx.core.http.impl.Http1xServerConnection.lambda$handleNext$1(Http1xServerConnection.java:225)
    at io.vertx.core.impl.EventLoopContext.emit(EventLoopContext.java:50)
    at io.vertx.core.impl.ContextImpl.emit(ContextImpl.java:274)
    at io.vertx.core.impl.EventLoopContext.emit(EventLoopContext.java:22)
    at io.vertx.core.http.impl.Http1xServerConnection.handleNext(Http1xServerConnection.java:222)
    at io.vertx.core.http.impl.Http1xServerConnection.responseComplete(Http1xServerConnection.java:207)
    at io.vertx.core.http.impl.Http1xServerResponse.end(Http1xServerResponse.java:418)
    at io.vertx.core.http.impl.Http1xServerResponse.end(Http1xServerResponse.java:391)
    at io.vertx.core.http.impl.Http1xServerResponse.end(Http1xServerResponse.java:370)
    at org.jboss.resteasy.reactive.server.vertx.VertxResteasyReactiveRequestContext.end(VertxResteasyReactiveRequestContext.java:349)
    at org.jboss.resteasy.reactive.server.providers.serialisers.ServerStringMessageBodyHandler.writeResponse(ServerStringMessageBodyHandler.java:26)
    at org.jboss.resteasy.reactive.server.core.ServerSerialisers.invokeWriter(ServerSerialisers.java:207)
    at org.jboss.resteasy.reactive.server.core.ServerSerialisers.invokeWriter(ServerSerialisers.java:178)
    at org.jboss.resteasy.reactive.server.core.serialization.FixedEntityWriter.write(FixedEntityWriter.java:26)
    at org.jboss.resteasy.reactive.server.handlers.ResponseWriterHandler.handle(ResponseWriterHandler.java:32)
    at org.jboss.resteasy.reactive.server.handlers.ResponseWriterHandler.handle(ResponseWriterHandler.java:15)
    at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:141)
    at org.jboss.resteasy.reactive.server.handlers.RestInitialHandler.beginProcessing(RestInitialHandler.java:49)
    at org.jboss.resteasy.reactive.server.vertx.ResteasyReactiveVertxHandler.handle(ResteasyReactiveVertxHandler.java:17)
    at org.jboss.resteasy.reactive.server.vertx.ResteasyReactiveVertxHandler.handle(ResteasyReactiveVertxHandler.java:7)
    at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1212)
    at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:163)
    at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
    at io.quarkus.vertx.http.runtime.VertxHttpRecorder$5.handle(VertxHttpRecorder.java:380)
    at io.quarkus.vertx.http.runtime.VertxHttpRecorder$5.handle(VertxHttpRecorder.java:358)
    at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1212)
    at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:163)
    at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
    at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$5.handle(VertxHttpHotReplacementSetup.java:196)
    at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$5.handle(VertxHttpHotReplacementSetup.java:185)
    at io.vertx.core.impl.future.FutureImpl$3.onSuccess(FutureImpl.java:141)
    at io.vertx.core.impl.future.FutureBase.lambda$emitSuccess$0(FutureBase.java:54)
    at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:503)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:829)
```

On quarkus 2.3.1 or lower this doesn't happen, quarkus 2.4.0 is the first version where this happens as far as I can tell.

### Expected behavior

HTTP 1.1 pipelined requests should not fail 

### Actual behavior

The second HTTP 1.1 pipelined request fails with an exception and the response for the second request is never sent

### How to Reproduce?

1. Create a GET point on / path
2. Start quarkus >= 2.4.0 in dev mode with `quarkus:dev`
3. Send 2 http pipelined requests with  `echo -en "GET / HTTP/1.1\\r\\nHost: localhost\\r\\n\\r\\nGET / HTTP/1.1\\r\\nHost: localhost\\r\\n\\r\\n" | nc localhost 8080`

### Output of `uname -a` or `ver`

Linux g8 5.13.0-37-generic #42-Ubuntu SMP Tue Mar 15 14:34:06 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

### Output of `java -version`

openjdk version "17.0.2" 2022-01-18 OpenJDK Runtime Environment (build 17.0.2+8-Ubuntu-122.10) OpenJDK 64-Bit Server VM (build 17.0.2+8-Ubuntu-122.10, mixed mode, sharing)

### GraalVM version (if different from Java)

NA

### Quarkus version or git rev

2.4.0, 2.7.5, 2.8.0.CR1

### Build tool (ie. output of `mvnw --version` or `gradlew --version`)

Apache Maven 3.8.4 (9b656c72d54e5bacbed989b64718c159fe39b537)

### Additional information

_No response_

Changed files:
extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java

diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java
index e9616ef08ad..cfb398cc681 100644
--- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java
+++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java
@@ -501,8 +501,22 @@ public void handle(HttpServerRequest event) {
         root = new Handler<HttpServerRequest>() {
             @Override
             public void handle(HttpServerRequest event) {
-                setCurrentContextSafe(true);
-                delegate.handle(new ResumingRequestWrapper(event));
+                if (!VertxContext.isOnDuplicatedContext()) {
+                    // Vert.x should call us on a duplicated context.
+                    // But in the case of pipelined requests, it does not.
+                    // See https://github.com/quarkusio/quarkus/issues/24626.
+                    Context context = VertxContext.createNewDuplicatedContext();
+                    context.runOnContext(new Handler<Void>() {
+                        @Override
+                        public void handle(Void x) {
+                            setCurrentContextSafe(true);
+                            delegate.handle(new ResumingRequestWrapper(event));
+                        }
+                    });
+                } else {
+                    setCurrentContextSafe(true);
+                    delegate.handle(new ResumingRequestWrapper(event));
+                }
             }
         };
         if (httpConfiguration.recordRequestStartTime) {