diff --git a/webserver/webserver/src/main/java/io/helidon/webserver/UriComponent.java b/common/http/src/main/java/io/helidon/common/http/UriComponent.java
similarity index 88%
rename from webserver/webserver/src/main/java/io/helidon/webserver/UriComponent.java
rename to common/http/src/main/java/io/helidon/common/http/UriComponent.java
index f8be1df7c40..1f64e728ae4 100644
--- a/webserver/webserver/src/main/java/io/helidon/webserver/UriComponent.java
+++ b/common/http/src/main/java/io/helidon/common/http/UriComponent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021 Oracle and/or its affiliates.
+ * Copyright (c) 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,24 +14,18 @@
* limitations under the License.
*/
-package io.helidon.webserver;
+package io.helidon.common.http;
import java.net.URLDecoder;
-import io.helidon.common.http.HashParameters;
-import io.helidon.common.http.Parameters;
-
import static java.nio.charset.StandardCharsets.UTF_8;
/**
* Extracted from Jersey
*
* Utility class for validating, encoding and decoding components of a URI.
- *
- * @author Paul Sandoz
- * @author Marek Potociar (marek.potociar at oracle.com)
*/
-final class UriComponent {
+public final class UriComponent {
private UriComponent() {
}
@@ -47,7 +41,7 @@ private UriComponent() {
* should be in decoded form.
* @return the multivalued map of query parameters.
*/
- static Parameters decodeQuery(String query, boolean decode) {
+ public static Parameters decodeQuery(String query, boolean decode) {
return decodeQuery(query, true, decode);
}
@@ -64,7 +58,7 @@ static Parameters decodeQuery(String query, boolean decode) {
* should be in decoded form.
* @return the multivalued map of query parameters.
*/
- static Parameters decodeQuery(String query, boolean decodeNames, boolean decodeValues) {
+ public static Parameters decodeQuery(String query, boolean decodeNames, boolean decodeValues) {
Parameters queryParameters = HashParameters.create();
if (query == null || query.isEmpty()) {
diff --git a/webserver/webserver/src/test/java/io/helidon/webserver/UriComponentTest.java b/common/http/src/test/java/io/helidon/common/http/UriComponentTest.java
similarity index 94%
rename from webserver/webserver/src/test/java/io/helidon/webserver/UriComponentTest.java
rename to common/http/src/test/java/io/helidon/common/http/UriComponentTest.java
index db26ac03e2a..0d90ee4cd3a 100644
--- a/webserver/webserver/src/test/java/io/helidon/webserver/UriComponentTest.java
+++ b/common/http/src/test/java/io/helidon/common/http/UriComponentTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021 Oracle and/or its affiliates.
+ * Copyright (c) 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,14 +14,12 @@
* limitations under the License.
*/
-package io.helidon.webserver;
+package io.helidon.common.http;
import java.net.URI;
import java.net.URLEncoder;
import java.util.Optional;
-import io.helidon.common.http.Parameters;
-
import org.junit.jupiter.api.Test;
import static java.nio.charset.StandardCharsets.US_ASCII;
diff --git a/webserver/tyrus/pom.xml b/webserver/tyrus/pom.xml
index 924a7a8ae62..e9b34f28c76 100644
--- a/webserver/tyrus/pom.xml
+++ b/webserver/tyrus/pom.xml
@@ -43,6 +43,10 @@
io.helidon.common
helidon-common-reactive
+
+ io.helidon.common
+ helidon-common-http
+
jakarta.websocket
jakarta.websocket-api
diff --git a/webserver/tyrus/src/main/java/io/helidon/webserver/tyrus/TyrusSupport.java b/webserver/tyrus/src/main/java/io/helidon/webserver/tyrus/TyrusSupport.java
index d4a19db2566..149eedf74a8 100644
--- a/webserver/tyrus/src/main/java/io/helidon/webserver/tyrus/TyrusSupport.java
+++ b/webserver/tyrus/src/main/java/io/helidon/webserver/tyrus/TyrusSupport.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2021 Oracle and/or its affiliates.
+ * Copyright (c) 2020, 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,7 +19,9 @@
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
@@ -31,6 +33,8 @@
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
+import io.helidon.common.http.Parameters;
+import io.helidon.common.http.UriComponent;
import io.helidon.webserver.Handler;
import io.helidon.webserver.Routing;
import io.helidon.webserver.ServerRequest;
@@ -265,9 +269,14 @@ public void accept(ServerRequest req, ServerResponse res) {
LOGGER.fine("Initiating WebSocket handshake ...");
- // Create Tyrus request context and copy request headers
+ // Create Tyrus request context, copying headers and query params
+ Map paramsMap = new HashMap<>();
+ Parameters params = UriComponent.decodeQuery(req.uri().getRawQuery(), true);
+ params.toMap().forEach((key, value) -> paramsMap.put(key, value.toArray(new String[0])));
RequestContext requestContext = RequestContext.Builder.create()
.requestURI(URI.create(req.path().toString())) // excludes context path
+ .queryString(req.query())
+ .parameterMap(paramsMap)
.build();
req.headers().toMap().forEach((key, value) -> requestContext.getHeaders().put(key, value));
diff --git a/webserver/tyrus/src/main/java/module-info.java b/webserver/tyrus/src/main/java/module-info.java
index 09a0e97fc8a..c34df61495c 100644
--- a/webserver/tyrus/src/main/java/module-info.java
+++ b/webserver/tyrus/src/main/java/module-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
requires io.helidon.common.context;
requires io.helidon.common.mapper;
requires io.helidon.common.reactive;
+ requires io.helidon.common.http;
requires tyrus.core;
requires tyrus.server;
diff --git a/webserver/tyrus/src/test/java/io/helidon/webserver/tyrus/EchoEndpoint.java b/webserver/tyrus/src/test/java/io/helidon/webserver/tyrus/EchoEndpoint.java
index 8e06b799ae3..3cbbb7c7416 100644
--- a/webserver/tyrus/src/test/java/io/helidon/webserver/tyrus/EchoEndpoint.java
+++ b/webserver/tyrus/src/test/java/io/helidon/webserver/tyrus/EchoEndpoint.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -62,6 +62,24 @@ private static void verifyRunningThread(Session session, Logger logger) throws I
}
}
+ /**
+ * Verify session includes expected query params.
+ *
+ * @param session Websocket session.
+ * @param logger A logger.
+ * @throws IOException Exception during close.
+ */
+ private static void verifyQueryParams(Session session, Logger logger) throws IOException {
+ if (!"user=Helidon".equals(session.getQueryString())) {
+ logger.warning("Websocket session does not include required query params");
+ session.close();
+ }
+ if (!session.getRequestParameterMap().get("user").get(0).equals("Helidon")) {
+ logger.warning("Websocket session does not include required query parameter map");
+ session.close();
+ }
+ }
+
public static class ServerConfigurator extends ServerEndpointConfig.Configurator {
@Override
@@ -76,6 +94,7 @@ public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request,
public void onOpen(Session session) throws IOException {
LOGGER.info("OnOpen called");
verifyRunningThread(session, LOGGER);
+ verifyQueryParams(session, LOGGER);
if (!modifyHandshakeCalled.get()) {
session.close(); // unexpected
}
@@ -85,6 +104,7 @@ public void onOpen(Session session) throws IOException {
public void echo(Session session, String message) throws Exception {
LOGGER.info("Endpoint OnMessage called '" + message + "'");
verifyRunningThread(session, LOGGER);
+ verifyQueryParams(session, LOGGER);
if (!isDecoded(message)) {
throw new InternalError("Message has not been decoded");
}
@@ -101,6 +121,7 @@ public void onError(Throwable t) {
public void onClose(Session session) throws IOException {
LOGGER.info("OnClose called");
verifyRunningThread(session, LOGGER);
+ verifyQueryParams(session, LOGGER);
modifyHandshakeCalled.set(false);
}
}
diff --git a/webserver/tyrus/src/test/java/io/helidon/webserver/tyrus/EchoServiceTest.java b/webserver/tyrus/src/test/java/io/helidon/webserver/tyrus/EchoServiceTest.java
index 1a8f3b4c465..adbf71db838 100644
--- a/webserver/tyrus/src/test/java/io/helidon/webserver/tyrus/EchoServiceTest.java
+++ b/webserver/tyrus/src/test/java/io/helidon/webserver/tyrus/EchoServiceTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,7 +36,7 @@ public static void startServer() throws Exception {
@Test
public void testEchoSingle() {
try {
- URI uri = URI.create("ws://localhost:" + webServer().port() + "/tyrus/echo");
+ URI uri = URI.create("ws://localhost:" + webServer().port() + "/tyrus/echo?user=Helidon");
new EchoClient(uri).echo("One");
} catch (Exception e) {
fail("Unexpected exception " + e);
@@ -46,7 +46,7 @@ public void testEchoSingle() {
@Test
public void testEchoMultiple() {
try {
- URI uri = URI.create("ws://localhost:" + webServer().port() + "/tyrus/echo");
+ URI uri = URI.create("ws://localhost:" + webServer().port() + "/tyrus/echo?user=Helidon");
new EchoClient(uri).echo("One", "Two", "Three");
} catch (Exception e) {
fail("Unexpected exception " + e);
diff --git a/webserver/tyrus/src/test/java/io/helidon/webserver/tyrus/HttpClientTest.java b/webserver/tyrus/src/test/java/io/helidon/webserver/tyrus/HttpClientTest.java
index 0a0c797a67a..366365ce3ca 100644
--- a/webserver/tyrus/src/test/java/io/helidon/webserver/tyrus/HttpClientTest.java
+++ b/webserver/tyrus/src/test/java/io/helidon/webserver/tyrus/HttpClientTest.java
@@ -43,7 +43,7 @@ static void startServer() throws ExecutionException, InterruptedException, Timeo
@Test
void testJdkClient() throws ExecutionException, InterruptedException, TimeoutException {
- URI uri = URI.create("ws://localhost:" + webServer().port() + "/tyrus/echo");
+ URI uri = URI.create("ws://localhost:" + webServer().port() + "/tyrus/echo?user=Helidon");
ClientListener listener = new ClientListener();
WebSocket webSocket = HttpClient.newHttpClient()
diff --git a/webserver/tyrus/src/test/java/io/helidon/webserver/tyrus/RoutingTest.java b/webserver/tyrus/src/test/java/io/helidon/webserver/tyrus/RoutingTest.java
index 3b8e8d56bd4..8d37851750c 100644
--- a/webserver/tyrus/src/test/java/io/helidon/webserver/tyrus/RoutingTest.java
+++ b/webserver/tyrus/src/test/java/io/helidon/webserver/tyrus/RoutingTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,7 +36,7 @@ public static void startServer() throws Exception {
@Test
public void testEcho() {
try {
- URI uri = URI.create("ws://localhost:" + webServer().port() + "/tyrus/echo");
+ URI uri = URI.create("ws://localhost:" + webServer().port() + "/tyrus/echo?user=Helidon");
new EchoClient(uri).echo("One");
} catch (Exception e) {
fail("Unexpected exception " + e);
@@ -46,7 +46,7 @@ public void testEcho() {
@Test
public void testDoubleEcho() {
try {
- URI uri = URI.create("ws://localhost:" + webServer().port() + "/tyrus/doubleEcho");
+ URI uri = URI.create("ws://localhost:" + webServer().port() + "/tyrus/doubleEcho?user=Helidon");
new EchoClient(uri, (s1, s2) -> s2.equals(s1 + s1)).echo("One");
} catch (Exception e) {
fail("Unexpected exception " + e);
diff --git a/webserver/webserver/src/main/java/io/helidon/webserver/Request.java b/webserver/webserver/src/main/java/io/helidon/webserver/Request.java
index 49720984183..8bdaa3a9bcc 100644
--- a/webserver/webserver/src/main/java/io/helidon/webserver/Request.java
+++ b/webserver/webserver/src/main/java/io/helidon/webserver/Request.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021 Oracle and/or its affiliates.
+ * Copyright (c) 2017, 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
import io.helidon.common.http.Http;
import io.helidon.common.http.MediaType;
import io.helidon.common.http.Parameters;
+import io.helidon.common.http.UriComponent;
import io.helidon.common.reactive.Single;
import io.helidon.media.common.MessageBodyContext;
import io.helidon.media.common.MessageBodyReadableContent;