Issue #3182 - restored old websocket example files

added new test for these example files

added register and setCreator methods in WebSocketServlet to
give more compatibility with old api

implemented isUserInRole in UpgradeHttpServletRequest to get
example working

made the JettyWebSocketTest more clear

Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
Lachlan Roberts 2019-01-23 18:43:54 +11:00
parent b06601e5f1
commit 90003dee13
12 changed files with 622 additions and 114 deletions

View File

@ -19,6 +19,7 @@
package org.eclipse.jetty.websocket.servlet;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.time.Duration;
import javax.servlet.ServletContext;
@ -182,78 +183,6 @@ public abstract class WebSocketServlet extends HttpServlet
return resources.getExtensionRegistry();
}
@Override
public Duration getIdleTimeout()
{
return getIdleTimeout();
}
@Override
public void setIdleTimeout(Duration duration)
{
setIdleTimeout(duration);
}
@Override
public int getInputBufferSize()
{
return getInputBufferSize();
}
@Override
public void setInputBufferSize(int bufferSize)
{
setInputBufferSize(bufferSize);
}
@Override
public long getMaxAllowedFrameSize()
{
return getMaxFrameSize();
}
@Override
public void setAllowedFrameSize(long maxFrameSize)
{
setMaxFrameSize(maxFrameSize);
}
@Override
public long getMaxBinaryMessageSize()
{
return getMaxBinaryMessageSize();
}
@Override
public void setMaxBinaryMessageSize(long size)
{
setMaxBinaryMessageSize(size);
}
@Override
public long getMaxTextMessageSize()
{
return getMaxTextMessageSize();
}
@Override
public void setMaxTextMessageSize(long size)
{
setMaxTextMessageSize(size);
}
@Override
public int getOutputBufferSize()
{
return getOutputBufferSize();
}
@Override
public void setOutputBufferSize(int bufferSize)
{
setOutputBufferSize(bufferSize);
}
@Override
public void addMapping(String pathSpec, WebSocketCreator creator)
{
@ -274,6 +203,41 @@ public abstract class WebSocketServlet extends HttpServlet
mapping.addMapping(pathSpec, creator, frameHandlerFactory, this);
}
@Override
public void register(Class<?> endpointClass)
{
Constructor<?> constructor;
try
{
constructor = endpointClass.getDeclaredConstructor(null);
}
catch (NoSuchMethodException e)
{
throw new RuntimeException(e);
}
WebSocketCreator creator = (req, resp) ->
{
try
{
return constructor.newInstance();
}
catch (Throwable t)
{
t.printStackTrace();
return null;
}
};
addMapping("/", creator);
}
@Override
public void setCreator(WebSocketCreator creator)
{
addMapping("/", creator);
}
@Override
public WebSocketCreator getMapping(PathSpec pathSpec)
{

View File

@ -36,9 +36,9 @@ public interface WebSocketServletFactory
void setInputBufferSize(int bufferSize);
long getMaxAllowedFrameSize();
long getMaxFrameSize();
void setAllowedFrameSize(long maxFrameSize);
void setMaxFrameSize(long maxFrameSize);
long getMaxBinaryMessageSize();
@ -72,6 +72,20 @@ public interface WebSocketServletFactory
*/
void addMapping(PathSpec pathSpec, WebSocketCreator creator);
/**
* Add a WebSocket mapping at PathSpec "/" for a creator which creates the endpointClass
*
* @param endpointClass the WebSocket class to use
*/
void register(Class<?> endpointClass);
/**
* Add a WebSocket mapping at PathSpec "/" for a creator
*
* @param creator the WebSocketCreator to use
*/
void setCreator(WebSocketCreator creator);
/**
* Returns the creator for the given path spec.
*

View File

@ -18,6 +18,19 @@
package org.eclipse.jetty.websocket.servlet.internal;
import java.io.BufferedReader;
import java.net.InetSocketAddress;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
@ -31,18 +44,10 @@ import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpUpgradeHandler;
import javax.servlet.http.Part;
import java.io.BufferedReader;
import java.net.InetSocketAddress;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.UserIdentity;
/**
* An immutable, feature limited, HttpServletRequest that will not be recycled by Jetty.
@ -67,6 +72,8 @@ public class UpgradeHttpServletRequest implements HttpServletRequest
private final Cookie[] cookies;
private final String remoteUser;
private final Principal principal;
private final Authentication authentication;
private final UserIdentity.Scope scope;
private final Map<String, List<String>> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
private final Map<String, String[]> parameters = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
@ -104,6 +111,8 @@ public class UpgradeHttpServletRequest implements HttpServletRequest
remoteUser = httpRequest.getRemoteUser();
principal = httpRequest.getUserPrincipal();
authentication = Request.getBaseRequest(httpRequest).getAuthentication();
scope = Request.getBaseRequest(httpRequest).getUserIdentityScope();
Enumeration<String> headerNames = httpRequest.getHeaderNames();
while (headerNames.hasMoreElements())
@ -220,7 +229,10 @@ public class UpgradeHttpServletRequest implements HttpServletRequest
@Override
public boolean isUserInRole(String role)
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
if (authentication instanceof Authentication.User)
return ((Authentication.User)authentication).isUserInRole(scope, role);
return false;
}
@Override

View File

@ -47,34 +47,26 @@ public class JettyWebsocketTest
public static class EventSocket
{
CountDownLatch closed = new CountDownLatch(1);
String id;
public EventSocket()
{
id = "";
}
public EventSocket(String id)
{
this.id = id;
}
String behavior;
@OnWebSocketConnect
public void onOpen(Session sess)
{
System.out.println("["+id+"]Socket Connected: " + sess);
behavior = sess.getPolicy().getBehavior().name();
System.err.println(toString() + " Socket Connected: " + sess);
}
@OnWebSocketMessage
public void onMessage(String message)
{
System.out.println("["+id+"]Received TEXT message: " + message);
System.err.println(toString() + " Received TEXT message: " + message);
}
@OnWebSocketClose
public void onClose(int statusCode, String reason)
{
System.out.println("["+id+"]Socket Closed: " + statusCode + ":" + reason);
System.err.println(toString() + " Socket Closed: " + statusCode + ":" + reason);
closed.countDown();
}
@ -83,25 +75,20 @@ public class JettyWebsocketTest
{
cause.printStackTrace(System.err);
}
}
public static class MyWebSocketServlet1 extends WebSocketServlet
{
@Override
public void configure(WebSocketServletFactory factory)
public String toString()
{
System.err.println("Configuring MyWebSocketServlet1");
factory.addMapping("/",(req, resp)->new EventSocket("MyWebSocketServlet1"));
return String.format("[%s@%s]", behavior, Integer.toHexString(hashCode()));
}
}
public static class MyWebSocketServlet2 extends WebSocketServlet
public static class MyWebSocketServlet extends WebSocketServlet
{
@Override
public void configure(WebSocketServletFactory factory)
{
System.err.println("Configuring MyWebSocketServlet2");
factory.addMapping("/",(req, resp)->new EventSocket("MyWebSocketServlet2"));
factory.addMapping("/",(req, resp)->new EventSocket());
}
}
@ -118,20 +105,18 @@ public class JettyWebsocketTest
contextHandler.setContextPath("/");
server.setHandler(contextHandler);
contextHandler.addServlet(MyWebSocketServlet1.class, "/testPath1");
contextHandler.addServlet(MyWebSocketServlet2.class, "/testPath2");
contextHandler.addServlet(MyWebSocketServlet.class, "/testPath1");
contextHandler.addServlet(MyWebSocketServlet.class, "/testPath2");
try
{
JettyWebSocketServletContainerInitializer.configure(contextHandler);
server.start();
URI uri = URI.create("ws://localhost:8080/testPath1");
WebSocketClient client = new WebSocketClient();
client.start();
URI uri = URI.create("ws://localhost:8080/testPath1");
EventSocket socket = new EventSocket();
CompletableFuture<Session> connect = client.connect(socket, uri);
try(Session session = connect.get(5, TimeUnit.SECONDS))

View File

@ -0,0 +1,226 @@
//
// ========================================================================
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.websocket.tests;
import java.net.URI;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.client.api.AuthenticationStore;
import org.eclipse.jetty.client.util.BasicAuthentication;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.security.UserStore;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.security.Credential;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.jetty.websocket.server.JettyWebSocketServletContainerInitializer;
import org.eclipse.jetty.websocket.tests.examples.MyAdvancedEchoServlet;
import org.eclipse.jetty.websocket.tests.examples.MyAuthedServlet;
import org.eclipse.jetty.websocket.tests.examples.MyEchoServlet;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class WebSocketServletExamplesTest
{
@WebSocket
public static class ClientSocket
{
CountDownLatch closed = new CountDownLatch(1);
ArrayBlockingQueue<String> messageQueue = new ArrayBlockingQueue<>(2);
@OnWebSocketConnect
public void onOpen(Session sess)
{
System.err.println("ClientSocket Connected: " + sess);
}
@OnWebSocketMessage
public void onMessage(String message)
{
messageQueue.offer(message);
System.err.println("Received TEXT message: " + message);
}
@OnWebSocketClose
public void onClose(int statusCode, String reason)
{
System.err.println("ClientSocket Closed: " + statusCode + ":" + reason);
closed.countDown();
}
@OnWebSocketError
public void onError(Throwable cause)
{
cause.printStackTrace(System.err);
}
}
static Server _server;
static ServletContextHandler _context;
@BeforeAll
public static void setup() throws Exception
{
_server = new Server();
ServerConnector connector = new ServerConnector(_server);
connector.setPort(8080);
_server.addConnector(connector);
_context = new ServletContextHandler(ServletContextHandler.SESSIONS);
_context.setContextPath("/");
_context.setSecurityHandler(getSecurityHandler("user", "password", "testRealm"));
_server.setHandler(_context);
_context.addServlet(MyEchoServlet.class, "/echo");
_context.addServlet(MyAdvancedEchoServlet.class, "/advancedEcho");
_context.addServlet(MyAuthedServlet.class, "/authed");
JettyWebSocketServletContainerInitializer.configure(_context);
_server.start();
}
@AfterAll
public static void stop() throws Exception
{
_server.stop();
}
private static SecurityHandler getSecurityHandler(String username, String password, String realm) {
HashLoginService loginService = new HashLoginService();
UserStore userStore = new UserStore();
userStore.addUser(username, Credential.getCredential(password), new String[] {"websocket"});
loginService.setUserStore(userStore);
loginService.setName(realm);
Constraint constraint = new Constraint();
constraint.setName("auth");
constraint.setAuthenticate(true);
constraint.setRoles(new String[]{"**"});
ConstraintMapping mapping = new ConstraintMapping();
mapping.setPathSpec("/authed/*");
mapping.setConstraint(constraint);
ConstraintSecurityHandler security = new ConstraintSecurityHandler();
security.addConstraintMapping(mapping);
security.setAuthenticator(new BasicAuthenticator());
security.setLoginService(loginService);
return security;
}
@Test
public void testEchoServlet() throws Exception
{
WebSocketClient client = new WebSocketClient();
client.start();
URI uri = URI.create("ws://localhost:8080/echo");
ClientSocket socket = new ClientSocket();
CompletableFuture<Session> connect = client.connect(socket, uri);
try (Session session = connect.get(5, TimeUnit.SECONDS))
{
String message = "hello world";
session.getRemote().sendString(message);
String response = socket.messageQueue.poll(5, TimeUnit.SECONDS);
assertThat(response, is(message));
}
assertTrue(socket.closed.await(10, TimeUnit.SECONDS));
}
@Test
public void testAdvancedEchoServlet() throws Exception
{
WebSocketClient client = new WebSocketClient();
client.start();
URI uri = URI.create("ws://localhost:8080/advancedEcho");
ClientSocket socket = new ClientSocket();
UpgradeRequest upgradeRequest = new ClientUpgradeRequest();
upgradeRequest.setSubProtocols("text");
CompletableFuture<Session> connect = client.connect(socket, uri, upgradeRequest);
try (Session session = connect.get(5, TimeUnit.SECONDS))
{
String message = "hello world";
session.getRemote().sendString(message);
String response = socket.messageQueue.poll(5, TimeUnit.SECONDS);
assertThat(response, is(message));
}
assertTrue(socket.closed.await(10, TimeUnit.SECONDS));
}
@Test
public void testAuthedServlet() throws Exception
{
WebSocketClient client = new WebSocketClient();
client.start();
AuthenticationStore authenticationStore = client.getHttpClient().getAuthenticationStore();
URI uri = URI.create("ws://localhost:8080/authed");
BasicAuthentication basicAuthentication = new BasicAuthentication(uri, "testRealm", "user", "password");
authenticationStore.addAuthentication(basicAuthentication);
ClientSocket socket = new ClientSocket();
CompletableFuture<Session> connect = client.connect(socket, uri);
try (Session session = connect.get(5, TimeUnit.SECONDS))
{
String message = "hello world";
session.getRemote().sendString(message);
String response = socket.messageQueue.poll(5, TimeUnit.SECONDS);
assertThat(response, is(message));
}
assertTrue(socket.closed.await(10, TimeUnit.SECONDS));
}
}

View File

@ -0,0 +1,57 @@
//
// ========================================================================
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.websocket.tests.examples;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
public class MyAdvancedEchoCreator implements WebSocketCreator
{
private MyBinaryEchoSocket binaryEcho;
private MyEchoSocket textEcho;
public MyAdvancedEchoCreator()
{
// Create the reusable sockets
this.binaryEcho = new MyBinaryEchoSocket();
this.textEcho = new MyEchoSocket();
}
@Override
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
{
for (String subprotocol : req.getSubProtocols())
{
if ("binary".equals(subprotocol))
{
resp.setAcceptedSubProtocol(subprotocol);
return binaryEcho;
}
if ("text".equals(subprotocol))
{
resp.setAcceptedSubProtocol(subprotocol);
return textEcho;
}
}
// No valid subprotocol in request, ignore the request
return null;
}
}

View File

@ -0,0 +1,41 @@
//
// ========================================================================
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.websocket.tests.examples;
import java.time.Duration;
import javax.servlet.annotation.WebServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
@SuppressWarnings("serial")
@WebServlet(name = "MyAdvanced Echo WebSocket Servlet", urlPatterns = { "/advecho" })
public class MyAdvancedEchoServlet extends WebSocketServlet
{
@Override
public void configure(WebSocketServletFactory factory)
{
// set a 10 second timeout
factory.setIdleTimeout(Duration.ofSeconds(10));
// set a custom WebSocket creator
factory.setCreator(new MyAdvancedEchoCreator());
}
}

View File

@ -0,0 +1,60 @@
//
// ========================================================================
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.websocket.tests.examples;
import java.io.IOException;
import java.security.Principal;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
public class MyAuthedCreator implements WebSocketCreator
{
@Override
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
{
try
{
// Is Authenticated?
Principal principal = req.getUserPrincipal();
if (principal == null)
{
resp.sendForbidden("Not authenticated yet");
return null;
}
// Is Authorized?
if (!req.isUserInRole("websocket"))
{
resp.sendForbidden("Not authenticated yet");
return null;
}
// Return websocket
return new MyEchoSocket();
}
catch (IOException e)
{
e.printStackTrace(System.err);
}
// no websocket
return null;
}
}

View File

@ -0,0 +1,32 @@
//
// ========================================================================
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.websocket.tests.examples;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
@SuppressWarnings("serial")
public class MyAuthedServlet extends WebSocketServlet
{
@Override
public void configure(WebSocketServletFactory factory)
{
factory.setCreator(new MyAuthedCreator());
}
}

View File

@ -0,0 +1,39 @@
//
// ========================================================================
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.websocket.tests.examples;
import java.nio.ByteBuffer;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
/**
* Echo BINARY messages
*/
@WebSocket
public class MyBinaryEchoSocket
{
@OnWebSocketMessage
public void onWebSocketText(Session session, byte buf[], int offset, int len)
{
// Echo message back, asynchronously
session.getRemote().sendBytes(ByteBuffer.wrap(buf,offset,len), null);
}
}

View File

@ -0,0 +1,41 @@
//
// ========================================================================
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.websocket.tests.examples;
import java.time.Duration;
import javax.servlet.annotation.WebServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
@SuppressWarnings("serial")
@WebServlet(name = "MyEcho WebSocket Servlet", urlPatterns = { "/echo" })
public class MyEchoServlet extends WebSocketServlet
{
@Override
public void configure(WebSocketServletFactory factory)
{
// set a 10 second timeout
factory.setIdleTimeout(Duration.ofSeconds(10));
// register MyEchoSocket as the WebSocket to create on Upgrade
factory.register(MyEchoSocket.class);
}
}

View File

@ -0,0 +1,37 @@
//
// ========================================================================
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.websocket.tests.examples;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
/**
* Example WebSocket, simple echo
*/
@WebSocket
public class MyEchoSocket
{
@OnWebSocketMessage
public void onWebSocketText(Session session, String message)
{
// Echo message back, asynchronously
session.getRemote().sendString(message, null);
}
}