diff --git a/bom/application/pom.xml b/bom/application/pom.xml
index f1ee28fd90596..a9a511de263eb 100644
--- a/bom/application/pom.xml
+++ b/bom/application/pom.xml
@@ -4151,6 +4151,11 @@
mockito-core
${mockito.version}
+
+ org.mockito
+ mockito-inline
+ ${mockito.version}
+
org.mockito
mockito-junit-jupiter
diff --git a/extensions/google-cloud-functions-http/runtime/pom.xml b/extensions/google-cloud-functions-http/runtime/pom.xml
index afaf187dcc707..5dd813408f4ea 100644
--- a/extensions/google-cloud-functions-http/runtime/pom.xml
+++ b/extensions/google-cloud-functions-http/runtime/pom.xml
@@ -32,6 +32,26 @@
functions-framework-api
provided
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ test
+
+
+ org.mockito
+ mockito-core
+ test
+
+
+ org.mockito
+ mockito-inline
+ test
+
diff --git a/extensions/google-cloud-functions-http/runtime/src/main/java/io/quarkus/gcp/functions/http/QuarkusHttpFunction.java b/extensions/google-cloud-functions-http/runtime/src/main/java/io/quarkus/gcp/functions/http/QuarkusHttpFunction.java
index e761ea71cb49e..cc491f6b2da64 100644
--- a/extensions/google-cloud-functions-http/runtime/src/main/java/io/quarkus/gcp/functions/http/QuarkusHttpFunction.java
+++ b/extensions/google-cloud-functions-http/runtime/src/main/java/io/quarkus/gcp/functions/http/QuarkusHttpFunction.java
@@ -92,7 +92,7 @@ private void nettyDispatch(HttpRequest request, HttpResponse response)
String path = request.getPath();
Optional host = request.getFirstHeader("Host");
DefaultHttpRequest nettyRequest = new DefaultHttpRequest(HttpVersion.HTTP_1_1,
- HttpMethod.valueOf(request.getMethod()), path);
+ HttpMethod.valueOf(request.getMethod()), request.getQuery().map(q -> path + "?" + q).orElse(path));
if (host.isPresent()) {
nettyRequest.headers().set("Host", host.get());
}
@@ -142,6 +142,7 @@ public void handleMessage(Object msg) {
try {
if (msg instanceof io.netty.handler.codec.http.HttpResponse) {
io.netty.handler.codec.http.HttpResponse res = (io.netty.handler.codec.http.HttpResponse) msg;
+ response.setStatusCode(res.status().code(), res.status().reasonPhrase());
for (Map.Entry entry : res.headers()) {
response.appendHeader(entry.getKey(), entry.getValue());
}
diff --git a/extensions/google-cloud-functions-http/runtime/src/test/java/io/quarkus/gcp/functions/http/QuarkusHttpFunctionTest.java b/extensions/google-cloud-functions-http/runtime/src/test/java/io/quarkus/gcp/functions/http/QuarkusHttpFunctionTest.java
new file mode 100644
index 0000000000000..3e9b02ba7b1f9
--- /dev/null
+++ b/extensions/google-cloud-functions-http/runtime/src/test/java/io/quarkus/gcp/functions/http/QuarkusHttpFunctionTest.java
@@ -0,0 +1,109 @@
+package io.quarkus.gcp.functions.http;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.mockito.ArgumentCaptor;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+import com.google.cloud.functions.HttpRequest;
+import com.google.cloud.functions.HttpResponse;
+
+import io.netty.handler.codec.http.DefaultHttpRequest;
+import io.netty.handler.codec.http.DefaultHttpResponse;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import io.netty.handler.codec.http.HttpVersion;
+import io.quarkus.netty.runtime.virtual.VirtualClientConnection;
+import io.quarkus.netty.runtime.virtual.VirtualResponseHandler;
+import io.quarkus.runtime.Application;
+
+public class QuarkusHttpFunctionTest {
+ private static final long PROCESSING_TIMEOUT = TimeUnit.SECONDS.toMillis(1);
+
+ private static final String PATH = "test/path";
+ private static final String QUERY = "testParam1=testValue1&testParam2=testValue2";
+ private static final String HOST_HEADER = "Host";
+ private static final String HOST = "localhost";
+ private static final String METHOD = "GET";
+
+ private final Application application = mock(Application.class);
+ private final HttpRequest request = mock(HttpRequest.class);
+ private final HttpResponse response = mock(HttpResponse.class);
+ private final VirtualClientConnection> connection = mock(VirtualClientConnection.class);
+
+ @BeforeEach
+ public void mockSetup() {
+ when(request.getPath()).thenReturn(PATH);
+ when(request.getFirstHeader(eq(HOST_HEADER))).thenReturn(Optional.of(HOST));
+ when(request.getHeaders()).thenReturn(Collections.singletonMap(HOST_HEADER, Collections.singletonList(HOST)));
+ when(request.getMethod()).thenReturn(METHOD);
+ }
+
+ @SuppressWarnings({ "OptionalUsedAsFieldOrParameterType", "rawtypes", "unused" })
+ private void mockHttpFunction(Optional query, HttpResponseStatus status) {
+ when(request.getQuery()).thenReturn(query);
+ try (MockedStatic applicationMock = Mockito.mockStatic(Application.class)) {
+ applicationMock.when(Application::currentApplication).thenReturn(application);
+ QuarkusHttpFunction function = new QuarkusHttpFunction();
+ CompletableFuture requestFuture = CompletableFuture.supplyAsync(() -> {
+ try (MockedStatic connectionMock = Mockito.mockStatic(VirtualClientConnection.class)) {
+ connectionMock.when(() -> VirtualClientConnection.connect(any(), any())).thenAnswer(i -> {
+ VirtualResponseHandler handler = i.getArgument(0);
+ CompletableFuture