Merge pull request #2769 from eclipse/jetty-9.4.x-issue-2767-websocket-client-default-policy
Issue #2767 - WebSocket Policy on JSR356 ClientContainer not represented correctly
This commit is contained in:
commit
ee68e7fdec
|
@ -406,7 +406,7 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
|
|||
@Override
|
||||
public WebSocketPolicy getPolicy()
|
||||
{
|
||||
return scopeDelegate.getPolicy();
|
||||
return client.getPolicy();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -482,10 +482,11 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
|
|||
@Override
|
||||
public void setDefaultMaxBinaryMessageBufferSize(int max)
|
||||
{
|
||||
// overall message limit (used in non-streaming)
|
||||
client.getPolicy().setMaxBinaryMessageSize(max);
|
||||
// incoming streaming buffer size
|
||||
client.setMaxBinaryMessageBufferSize(max);
|
||||
|
||||
// bump overall message limit (used in non-streaming)
|
||||
client.getPolicy().setMaxBinaryMessageSize(max);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -497,9 +498,10 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
|
|||
@Override
|
||||
public void setDefaultMaxTextMessageBufferSize(int max)
|
||||
{
|
||||
// overall message limit (used in non-streaming)
|
||||
client.getPolicy().setMaxTextMessageSize(max);
|
||||
// incoming streaming buffer size
|
||||
client.setMaxTextMessageBufferSize(max);
|
||||
|
||||
// bump overall message limit (used in non-streaming)
|
||||
client.getPolicy().setMaxTextMessageSize(max);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -328,7 +328,11 @@ public class JsrSession extends WebSocketSession implements javax.websocket.Sess
|
|||
@Override
|
||||
public void setMaxBinaryMessageBufferSize(int length)
|
||||
{
|
||||
// incoming streaming buffer size
|
||||
getPolicy().setMaxBinaryMessageBufferSize(length);
|
||||
|
||||
// bump overall message limit (used in non-streaming)
|
||||
getPolicy().setMaxBinaryMessageSize(length);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -341,7 +345,11 @@ public class JsrSession extends WebSocketSession implements javax.websocket.Sess
|
|||
@Override
|
||||
public void setMaxTextMessageBufferSize(int length)
|
||||
{
|
||||
// incoming streaming buffer size
|
||||
getPolicy().setMaxTextMessageBufferSize(length);
|
||||
|
||||
// bump overall message limit (used in non-streaming)
|
||||
getPolicy().setMaxTextMessageSize(length);
|
||||
}
|
||||
|
||||
public void setPathParameters(Map<String, String> pathParams)
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.eclipse.jetty.util.log.Log;
|
|||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.BatchMode;
|
||||
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
|
||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketAdapter;
|
||||
|
||||
/**
|
||||
|
@ -78,4 +79,14 @@ public class JettyEchoSocket extends WebSocketAdapter
|
|||
throw new RuntimeIOException(x);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWebSocketClose(int statusCode, String reason)
|
||||
{
|
||||
super.onWebSocketClose(statusCode, reason);
|
||||
if (statusCode != StatusCode.NORMAL)
|
||||
{
|
||||
LOG.warn("Closed {} {}", statusCode, reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.jsr356;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.websocket.ContainerProvider;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.WebSocketContainer;
|
||||
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.util.WSURI;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class LargeMessageTest
|
||||
{
|
||||
private static final int LARGER_THAN_DEFAULT_SIZE;
|
||||
private Server server;
|
||||
|
||||
static
|
||||
{
|
||||
WebSocketPolicy defaultPolicy = new WebSocketPolicy(WebSocketBehavior.CLIENT);
|
||||
LARGER_THAN_DEFAULT_SIZE = defaultPolicy.getMaxTextMessageSize() * 3;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void startServer() throws Exception
|
||||
{
|
||||
server = new Server();
|
||||
ServerConnector connector = new ServerConnector(server);
|
||||
connector.setPort(0);
|
||||
server.addConnector(connector);
|
||||
|
||||
// This handler is expected to handle echoing of 2MB messages (max)
|
||||
EchoHandler echoHandler = new EchoHandler();
|
||||
|
||||
ContextHandler context = new ContextHandler();
|
||||
context.setContextPath("/");
|
||||
context.setHandler(echoHandler);
|
||||
server.setHandler(context);
|
||||
|
||||
server.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopServer() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
@Test
|
||||
public void testLargeEcho_AsEndpointInstance() throws Exception
|
||||
{
|
||||
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
|
||||
server.addBean(container); // allow to shutdown with server
|
||||
|
||||
container.setDefaultMaxTextMessageBufferSize(LARGER_THAN_DEFAULT_SIZE);
|
||||
|
||||
EndpointEchoClient echoer = new EndpointEchoClient();
|
||||
Assert.assertThat(echoer,instanceOf(javax.websocket.Endpoint.class));
|
||||
|
||||
URI wsUri = WSURI.toWebsocket(server.getURI()).resolve("/");
|
||||
|
||||
// Issue connect using instance of class that extends Endpoint
|
||||
Session session = container.connectToServer(echoer,wsUri);
|
||||
byte buf[] = new byte[LARGER_THAN_DEFAULT_SIZE];
|
||||
Arrays.fill(buf, (byte)'x');
|
||||
String message = new String(buf, UTF_8);
|
||||
session.getBasicRemote().sendText(message);
|
||||
|
||||
String echoed = echoer.textCapture.messages.poll(1, TimeUnit.SECONDS);
|
||||
assertThat("Echoed", echoed, is(message));
|
||||
}
|
||||
}
|
|
@ -20,76 +20,79 @@ package org.eclipse.jetty.websocket.jsr356.server;
|
|||
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.common.test.Timeouts;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.echo.LargeEchoConfiguredSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.echo.LargeEchoAnnotatedSocket;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Test Echo of Large messages, targeting the {@link javax.websocket.Session#setMaxTextMessageBufferSize(int)} functionality
|
||||
* Test Echo of Large messages, targeting the {@code @OnMessage(maxMessage=###)} functionality
|
||||
*/
|
||||
@Ignore
|
||||
public class LargeAnnotatedTest
|
||||
{
|
||||
@Rule
|
||||
public TestingDir testdir = new TestingDir();
|
||||
private static WSServer server;
|
||||
|
||||
public ByteBufferPool bufferPool = new MappedByteBufferPool();
|
||||
@BeforeClass
|
||||
public static void startServer() throws Exception
|
||||
{
|
||||
Path testDir = MavenTestingUtils.getTargetTestingPath(LargeOnOpenSessionConfiguredTest.class.getSimpleName());
|
||||
|
||||
server = new WSServer(testDir,"app");
|
||||
server.createWebInf();
|
||||
server.copyEndpoint(LargeEchoAnnotatedSocket.class);
|
||||
|
||||
server.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stopServer()
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
@Test
|
||||
public void testEcho() throws Exception
|
||||
{
|
||||
WSServer wsb = new WSServer(testdir,"app");
|
||||
wsb.createWebInf();
|
||||
wsb.copyEndpoint(LargeEchoConfiguredSocket.class);
|
||||
URI uri = server.getServerBaseURI();
|
||||
|
||||
WebAppContext webapp = server.createWebAppContext();
|
||||
server.deployWebapp(webapp);
|
||||
// wsb.dump();
|
||||
|
||||
WebSocketClient client = new WebSocketClient();
|
||||
try
|
||||
{
|
||||
wsb.start();
|
||||
URI uri = wsb.getServerBaseURI();
|
||||
client.getPolicy().setMaxTextMessageSize(128*1024);
|
||||
client.start();
|
||||
JettyEchoSocket clientEcho = new JettyEchoSocket();
|
||||
Future<Session> foo = client.connect(clientEcho,uri.resolve("echo/large"));
|
||||
|
||||
WebAppContext webapp = wsb.createWebAppContext();
|
||||
wsb.deployWebapp(webapp);
|
||||
// wsb.dump();
|
||||
|
||||
WebSocketClient client = new WebSocketClient(bufferPool);
|
||||
try
|
||||
{
|
||||
client.getPolicy().setMaxTextMessageSize(128*1024);
|
||||
client.start();
|
||||
JettyEchoSocket clientEcho = new JettyEchoSocket();
|
||||
Future<Session> foo = client.connect(clientEcho,uri.resolve("echo/large"));
|
||||
// wait for connect
|
||||
foo.get(1,TimeUnit.SECONDS);
|
||||
// The message size should be bigger than default, but smaller than the limit that LargeEchoSocket specifies
|
||||
byte txt[] = new byte[100 * 1024];
|
||||
Arrays.fill(txt,(byte)'o');
|
||||
String msg = new String(txt,StandardCharsets.UTF_8);
|
||||
clientEcho.sendMessage(msg);
|
||||
LinkedBlockingQueue<String> msgs = clientEcho.incomingMessages;
|
||||
Assert.assertEquals("Expected message",msg,msgs.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT));
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
// wait for connect
|
||||
foo.get(1,TimeUnit.SECONDS);
|
||||
// The message size should be bigger than default, but smaller than the limit that LargeEchoSocket specifies
|
||||
byte txt[] = new byte[100 * 1024];
|
||||
Arrays.fill(txt,(byte)'o');
|
||||
String msg = new String(txt,StandardCharsets.UTF_8);
|
||||
clientEcho.sendMessage(msg);
|
||||
LinkedBlockingQueue<String> msgs = clientEcho.incomingMessages;
|
||||
Assert.assertEquals("Expected message",msg,msgs.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT));
|
||||
}
|
||||
finally
|
||||
{
|
||||
wsb.stop();
|
||||
client.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.jsr356.server;
|
||||
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
|
||||
import org.eclipse.jetty.websocket.jsr356.JettyClientContainerProvider;
|
||||
|
||||
public class LargeClientContainerInitAsServerListener implements ServletContextListener
|
||||
{
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce)
|
||||
{
|
||||
JettyClientContainerProvider.useServerContainer(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce)
|
||||
{
|
||||
/* ignore */
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.jsr356.server;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.websocket.ClientEndpoint;
|
||||
import javax.websocket.ContainerProvider;
|
||||
import javax.websocket.DeploymentException;
|
||||
import javax.websocket.OnMessage;
|
||||
import javax.websocket.OnOpen;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.WebSocketContainer;
|
||||
|
||||
import org.eclipse.jetty.util.BlockingArrayQueue;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
|
||||
public class LargeClientContainerServlet extends HttpServlet
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(LargeClientContainerServlet.class);
|
||||
private static final int LARGER_THAN_DEFAULT_SIZE;
|
||||
private WebSocketContainer clientContainer;
|
||||
|
||||
static
|
||||
{
|
||||
WebSocketPolicy defaultPolicy = new WebSocketPolicy(WebSocketBehavior.CLIENT);
|
||||
LARGER_THAN_DEFAULT_SIZE = defaultPolicy.getMaxTextMessageSize() * 3;
|
||||
}
|
||||
|
||||
private synchronized WebSocketContainer getClientContainer()
|
||||
{
|
||||
if(clientContainer == null)
|
||||
{
|
||||
clientContainer = ContainerProvider.getWebSocketContainer();
|
||||
clientContainer.setDefaultMaxTextMessageBufferSize(LARGER_THAN_DEFAULT_SIZE);
|
||||
}
|
||||
|
||||
return clientContainer;
|
||||
}
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException
|
||||
{
|
||||
int size = LARGER_THAN_DEFAULT_SIZE;
|
||||
|
||||
String sizeParam = req.getParameter("size");
|
||||
if(StringUtil.isNotBlank(sizeParam))
|
||||
{
|
||||
size = Integer.parseInt(sizeParam);
|
||||
}
|
||||
|
||||
byte buf[] = new byte[size];
|
||||
Arrays.fill(buf, (byte) 'x');
|
||||
|
||||
String destUrl = req.getParameter("destUrl");
|
||||
if(StringUtil.isBlank(destUrl))
|
||||
{
|
||||
resp.sendError(HttpServletResponse.SC_EXPECTATION_FAILED, "Missing destUrl");
|
||||
return;
|
||||
}
|
||||
|
||||
WebSocketContainer client = getClientContainer();
|
||||
URI wsUri = URI.create(destUrl);
|
||||
|
||||
try
|
||||
{
|
||||
Session session = client.connectToServer(EchoClientSocket.class, wsUri);
|
||||
EchoClientSocket clientSocket = (EchoClientSocket) session.getUserProperties().get("endpoint");
|
||||
String message = new String(buf, UTF_8);
|
||||
session.getBasicRemote().sendText(message);
|
||||
String echoed = clientSocket.messages.poll(1, TimeUnit.SECONDS);
|
||||
assertThat("Echoed", echoed, is(message));
|
||||
resp.setStatus(HttpServletResponse.SC_OK);
|
||||
resp.getWriter().println("Success");
|
||||
}
|
||||
catch (DeploymentException e)
|
||||
{
|
||||
LOG.warn("Unable to deploy client socket", e);
|
||||
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Deployment error");
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
LOG.warn("Unable to find echoed message", e);
|
||||
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Echoed message missing?");
|
||||
}
|
||||
}
|
||||
|
||||
@ClientEndpoint
|
||||
public static class EchoClientSocket
|
||||
{
|
||||
public BlockingArrayQueue<String> messages = new BlockingArrayQueue<>();
|
||||
|
||||
@OnOpen
|
||||
public void onOpen(Session session)
|
||||
{
|
||||
session.getUserProperties().put("endpoint", this);
|
||||
}
|
||||
|
||||
@OnMessage
|
||||
public void onMessage(String msg)
|
||||
{
|
||||
messages.offer(msg);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.jsr356.server;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.echo.LargeEchoAnnotatedSocket;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
/**
|
||||
* Test send of large messages from within a Server using a ClientContainer
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class LargeNestedClientContainerTest
|
||||
{
|
||||
public static abstract class WSServerConfig
|
||||
{
|
||||
private final String description;
|
||||
|
||||
public WSServerConfig(String description)
|
||||
{
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public abstract void configure(WSServer server) throws Exception;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return this.description;
|
||||
}
|
||||
}
|
||||
|
||||
@Parameterized.Parameters(name = "[{index}] {0}")
|
||||
public static List<WSServerConfig[]> usecases()
|
||||
{
|
||||
List<WSServerConfig[]> scenarios = new ArrayList<>();
|
||||
|
||||
scenarios.add(new WSServerConfig[]{
|
||||
new WSServerConfig("Servlet using ContainerProvider.getWebSocketContainer() (default)")
|
||||
{
|
||||
@Override
|
||||
public void configure(WSServer server) throws Exception
|
||||
{
|
||||
server.copyWebInf("large-client-container-servlet-web.xml");
|
||||
server.copyClass(LargeClientContainerServlet.class);
|
||||
server.copyEndpoint(LargeEchoAnnotatedSocket.class);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
scenarios.add(new WSServerConfig[]{
|
||||
new WSServerConfig("Servlet using ContainerProvider.getWebSocketContainer() (init / server-container)")
|
||||
{
|
||||
@Override
|
||||
public void configure(WSServer server) throws Exception
|
||||
{
|
||||
server.copyWebInf("large-client-container-servlet-init-use-server-web.xml");
|
||||
server.copyClass(LargeClientContainerInitAsServerListener.class);
|
||||
server.copyClass(LargeClientContainerServlet.class);
|
||||
server.copyEndpoint(LargeEchoAnnotatedSocket.class);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
scenarios.add(new WSServerConfig[]{
|
||||
new WSServerConfig("Servlet using ServerContainer as ClientContainer")
|
||||
{
|
||||
@Override
|
||||
public void configure(WSServer server) throws Exception
|
||||
{
|
||||
server.copyWebInf("large-client-container-servlet-web.xml");
|
||||
server.copyClass(LargeServerContainerAsClientContainerServlet.class);
|
||||
server.copyEndpoint(LargeEchoAnnotatedSocket.class);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return scenarios;
|
||||
}
|
||||
|
||||
private static final AtomicInteger appDirIdx = new AtomicInteger(0);
|
||||
|
||||
@Parameterized.Parameter
|
||||
public WSServerConfig serverConfig;
|
||||
|
||||
@Test
|
||||
public void testLargeEcho() throws Exception
|
||||
{
|
||||
Path testDir = MavenTestingUtils.getTargetTestingPath(LargeNestedClientContainerTest.class.getSimpleName() + "-" + appDirIdx.getAndIncrement());
|
||||
|
||||
WSServer server = new WSServer(testDir, "app");
|
||||
server.createWebInf();
|
||||
|
||||
serverConfig.configure(server);
|
||||
|
||||
try
|
||||
{
|
||||
server.start();
|
||||
|
||||
WebAppContext webapp = server.createWebAppContext();
|
||||
server.deployWebapp(webapp);
|
||||
|
||||
// server.dump();
|
||||
|
||||
HttpClient client = new HttpClient();
|
||||
try
|
||||
{
|
||||
client.start();
|
||||
|
||||
URI destUri = server.getServerBaseURI().resolve("/app/echo/large");
|
||||
String destUrl = URLEncoder.encode(destUri.toASCIIString(), "utf-8");
|
||||
|
||||
WebSocketPolicy defaultPolicy = new WebSocketPolicy(WebSocketBehavior.CLIENT);
|
||||
int defaultTextSize = defaultPolicy.getMaxTextMessageSize();
|
||||
|
||||
URI uri = server.getServer().getURI().resolve("/app/echo/servlet?size=" + (defaultTextSize * 2) + "&destUrl=" + destUrl);
|
||||
|
||||
ContentResponse response = client.GET(uri);
|
||||
|
||||
assertThat("Response.status", response.getStatus(), is(200));
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.jsr356.server;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.common.test.Timeouts;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.echo.LargeEchoConfiguredSocket;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Test Echo of Large messages, targeting the use of {@link javax.websocket.Session#setMaxTextMessageBufferSize(int)}
|
||||
* from within the {@code @OnOpen} method call functionality.
|
||||
*/
|
||||
public class LargeOnOpenSessionConfiguredTest
|
||||
{
|
||||
private WSServer server;
|
||||
|
||||
@Before
|
||||
public void startServer() throws Exception
|
||||
{
|
||||
Path testDir = MavenTestingUtils.getTargetTestingPath(LargeOnOpenSessionConfiguredTest.class.getSimpleName());
|
||||
|
||||
server = new WSServer(testDir,"app");
|
||||
server.createWebInf();
|
||||
server.copyEndpoint(LargeEchoConfiguredSocket.class);
|
||||
|
||||
server.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopServer()
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
@Test
|
||||
public void testEcho() throws Exception
|
||||
{
|
||||
URI uri = server.getServerBaseURI();
|
||||
|
||||
WebAppContext webapp = server.createWebAppContext();
|
||||
server.deployWebapp(webapp);
|
||||
// wsb.dump();
|
||||
|
||||
WebSocketClient client = new WebSocketClient();
|
||||
try
|
||||
{
|
||||
client.getPolicy().setMaxTextMessageSize(128 * 1024);
|
||||
client.start();
|
||||
JettyEchoSocket clientEcho = new JettyEchoSocket();
|
||||
Future<Session> foo = client.connect(clientEcho,uri.resolve("echo/large"));
|
||||
|
||||
// wait for connect
|
||||
foo.get(1,TimeUnit.SECONDS);
|
||||
// The message size should be bigger than default, but smaller than the limit that LargeEchoSocket specifies
|
||||
byte txt[] = new byte[100 * 1024];
|
||||
Arrays.fill(txt,(byte)'o');
|
||||
String msg = new String(txt,StandardCharsets.UTF_8);
|
||||
clientEcho.sendMessage(msg);
|
||||
LinkedBlockingQueue<String> msgs = clientEcho.incomingMessages;
|
||||
Assert.assertEquals("Expected message",msg,msgs.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT));
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.jsr356.server;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.websocket.ClientEndpoint;
|
||||
import javax.websocket.DeploymentException;
|
||||
import javax.websocket.OnMessage;
|
||||
import javax.websocket.OnOpen;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.WebSocketContainer;
|
||||
import javax.websocket.server.ServerContainer;
|
||||
|
||||
import org.eclipse.jetty.util.BlockingArrayQueue;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
|
||||
public class LargeServerContainerAsClientContainerServlet extends HttpServlet
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(LargeServerContainerAsClientContainerServlet.class);
|
||||
private static final int LARGER_THAN_DEFAULT_SIZE;
|
||||
private WebSocketContainer clientContainer;
|
||||
|
||||
static
|
||||
{
|
||||
WebSocketPolicy defaultPolicy = new WebSocketPolicy(WebSocketBehavior.CLIENT);
|
||||
LARGER_THAN_DEFAULT_SIZE = defaultPolicy.getMaxTextMessageSize() * 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() throws ServletException
|
||||
{
|
||||
super.init();
|
||||
|
||||
ServerContainer serverContainer = (ServerContainer) getServletContext().getAttribute(ServerContainer.class.getName());
|
||||
clientContainer = serverContainer;
|
||||
}
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException
|
||||
{
|
||||
int size = LARGER_THAN_DEFAULT_SIZE;
|
||||
|
||||
String sizeParam = req.getParameter("size");
|
||||
if(StringUtil.isNotBlank(sizeParam))
|
||||
{
|
||||
size = Integer.parseInt(sizeParam);
|
||||
}
|
||||
|
||||
byte buf[] = new byte[size];
|
||||
Arrays.fill(buf, (byte) 'x');
|
||||
|
||||
String destUrl = req.getParameter("destUrl");
|
||||
if(StringUtil.isBlank(destUrl))
|
||||
{
|
||||
resp.sendError(HttpServletResponse.SC_EXPECTATION_FAILED, "Missing destUrl");
|
||||
return;
|
||||
}
|
||||
|
||||
URI wsUri = URI.create(destUrl);
|
||||
|
||||
try
|
||||
{
|
||||
Session session = clientContainer.connectToServer(EchoClientSocket.class, wsUri);
|
||||
EchoClientSocket clientSocket = (EchoClientSocket) session.getUserProperties().get("endpoint");
|
||||
String message = new String(buf, UTF_8);
|
||||
session.getBasicRemote().sendText(message);
|
||||
String echoed = clientSocket.messages.poll(1, TimeUnit.SECONDS);
|
||||
assertThat("Echoed", echoed, is(message));
|
||||
resp.setStatus(HttpServletResponse.SC_OK);
|
||||
resp.getWriter().println("Success");
|
||||
}
|
||||
catch (DeploymentException e)
|
||||
{
|
||||
LOG.warn("Unable to deploy client socket", e);
|
||||
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Deployment error");
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
LOG.warn("Unable to find echoed message", e);
|
||||
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Echoed message missing?");
|
||||
}
|
||||
}
|
||||
|
||||
@ClientEndpoint
|
||||
public static class EchoClientSocket
|
||||
{
|
||||
public BlockingArrayQueue<String> messages = new BlockingArrayQueue<>();
|
||||
|
||||
@OnOpen
|
||||
public void onOpen(Session session)
|
||||
{
|
||||
session.getUserProperties().put("endpoint", this);
|
||||
}
|
||||
|
||||
@OnMessage
|
||||
public void onMessage(String msg)
|
||||
{
|
||||
messages.offer(msg);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,9 +22,9 @@ import static org.hamcrest.Matchers.notNullValue;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationConfiguration;
|
||||
import org.eclipse.jetty.plus.webapp.EnvConfiguration;
|
||||
|
@ -36,11 +36,10 @@ import org.eclipse.jetty.server.handler.HandlerCollection;
|
|||
import org.eclipse.jetty.toolchain.test.FS;
|
||||
import org.eclipse.jetty.toolchain.test.IO;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.toolchain.test.OS;
|
||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.util.resource.PathResource;
|
||||
import org.eclipse.jetty.webapp.Configuration;
|
||||
import org.eclipse.jetty.webapp.FragmentConfiguration;
|
||||
import org.eclipse.jetty.webapp.MetaInfConfiguration;
|
||||
|
@ -57,22 +56,27 @@ import org.junit.Assert;
|
|||
public class WSServer
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(WSServer.class);
|
||||
private final File contextDir;
|
||||
private final Path contextDir;
|
||||
private final String contextPath;
|
||||
private Server server;
|
||||
private URI serverUri;
|
||||
private ContextHandlerCollection contexts;
|
||||
private File webinf;
|
||||
private File classesDir;
|
||||
private Path webinf;
|
||||
private Path classesDir;
|
||||
|
||||
public WSServer(TestingDir testdir, String contextName)
|
||||
{
|
||||
this(testdir.getPath().toFile(),contextName);
|
||||
this(testdir.getPath(),contextName);
|
||||
}
|
||||
|
||||
public WSServer(File testdir, String contextName)
|
||||
{
|
||||
this.contextDir = new File(testdir,contextName);
|
||||
this(testdir.toPath(), contextName);
|
||||
}
|
||||
|
||||
public WSServer(Path testdir, String contextName)
|
||||
{
|
||||
this.contextDir = testdir.resolve(contextName);
|
||||
this.contextPath = "/" + contextName;
|
||||
FS.ensureEmpty(contextDir);
|
||||
}
|
||||
|
@ -83,10 +87,10 @@ public class WSServer
|
|||
String endpointPath = clazz.getName().replace('.','/') + ".class";
|
||||
URL classUrl = cl.getResource(endpointPath);
|
||||
Assert.assertThat("Class URL for: " + clazz,classUrl,notNullValue());
|
||||
File destFile = new File(classesDir,OS.separators(endpointPath));
|
||||
FS.ensureDirExists(destFile.getParentFile());
|
||||
File srcFile = new File(classUrl.toURI());
|
||||
IO.copy(srcFile,destFile);
|
||||
Path destFile = classesDir.resolve(endpointPath);
|
||||
FS.ensureDirExists(destFile.getParent());
|
||||
Path srcFile = new File(classUrl.toURI()).toPath();
|
||||
IO.copy(srcFile.toFile(),destFile.toFile());
|
||||
}
|
||||
|
||||
public void copyEndpoint(Class<?> endpointClass) throws Exception
|
||||
|
@ -96,23 +100,22 @@ public class WSServer
|
|||
|
||||
public void copyWebInf(String testResourceName) throws IOException
|
||||
{
|
||||
webinf = new File(contextDir,"WEB-INF");
|
||||
webinf = contextDir.resolve("WEB-INF");
|
||||
FS.ensureDirExists(webinf);
|
||||
classesDir = new File(webinf,"classes");
|
||||
classesDir = webinf.resolve("classes");
|
||||
FS.ensureDirExists(classesDir);
|
||||
File webxml = new File(webinf,"web.xml");
|
||||
File testWebXml = MavenTestingUtils.getTestResourceFile(testResourceName);
|
||||
IO.copy(testWebXml,webxml);
|
||||
Path webxml = webinf.resolve("web.xml");
|
||||
Path testWebXml = MavenTestingUtils.getTestResourcePath(testResourceName);
|
||||
IO.copy(testWebXml.toFile(),webxml.toFile());
|
||||
}
|
||||
|
||||
public WebAppContext createWebAppContext() throws MalformedURLException, IOException
|
||||
public WebAppContext createWebAppContext()
|
||||
{
|
||||
WebAppContext context = new WebAppContext();
|
||||
context.setContextPath(this.contextPath);
|
||||
context.setBaseResource(Resource.newResource(this.contextDir));
|
||||
context.setBaseResource(new PathResource(this.contextDir));
|
||||
context.setAttribute("org.eclipse.jetty.websocket.jsr356",Boolean.TRUE);
|
||||
|
||||
// @formatter:off
|
||||
context.setConfigurations(new Configuration[] {
|
||||
new AnnotationConfiguration(),
|
||||
new WebXmlConfiguration(),
|
||||
|
@ -121,7 +124,6 @@ public class WSServer
|
|||
new MetaInfConfiguration(),
|
||||
new FragmentConfiguration(),
|
||||
new EnvConfiguration()});
|
||||
// @formatter:on
|
||||
|
||||
return context;
|
||||
}
|
||||
|
@ -159,7 +161,7 @@ public class WSServer
|
|||
|
||||
public File getWebAppDir()
|
||||
{
|
||||
return this.contextDir;
|
||||
return this.contextDir.toFile();
|
||||
}
|
||||
|
||||
public void start() throws Exception
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.jsr356.server.samples.echo;
|
||||
|
||||
import javax.websocket.OnMessage;
|
||||
import javax.websocket.OnOpen;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
|
||||
/**
|
||||
* Annotated echo socket
|
||||
*/
|
||||
@ServerEndpoint(value = "/echo/large")
|
||||
public class LargeEchoAnnotatedSocket
|
||||
{
|
||||
private Session session;
|
||||
|
||||
@OnOpen
|
||||
public void open(Session session)
|
||||
{
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@OnMessage(maxMessageSize = 128 * 1024)
|
||||
public void echo(String msg)
|
||||
{
|
||||
// reply with echo
|
||||
session.getAsyncRemote().sendText(msg);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
metadata-complete="false"
|
||||
version="3.0">
|
||||
|
||||
<listener>
|
||||
<listener-class>org.eclipse.jetty.websocket.jsr356.server.LargeClientContainerInitAsServerListener</listener-class>
|
||||
</listener>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>large-client</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.websocket.jsr356.server.LargeClientContainerServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>large-client</servlet-name>
|
||||
<url-pattern>/echo/servlet</url-pattern>
|
||||
</servlet-mapping>
|
||||
</web-app>
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
metadata-complete="false"
|
||||
version="3.0">
|
||||
|
||||
<servlet>
|
||||
<servlet-name>large-client</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.websocket.jsr356.server.LargeClientContainerServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>large-client</servlet-name>
|
||||
<url-pattern>/echo/servlet</url-pattern>
|
||||
</servlet-mapping>
|
||||
</web-app>
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
metadata-complete="false"
|
||||
version="3.0">
|
||||
|
||||
<servlet>
|
||||
<servlet-name>large-client</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.websocket.jsr356.server.LargeServerContainerAsClientContainerServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>large-client</servlet-name>
|
||||
<url-pattern>/echo/servlet</url-pattern>
|
||||
</servlet-mapping>
|
||||
</web-app>
|
|
@ -142,22 +142,42 @@ public class WebSocketPolicy
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a copy of the policy, with current values.
|
||||
* @return the cloned copy of the policy.
|
||||
*/
|
||||
public WebSocketPolicy clonePolicy()
|
||||
{
|
||||
return clonePolicy(this.behavior);
|
||||
WebSocketPolicy clone = new WebSocketPolicy(this.behavior);
|
||||
clone.idleTimeout = this.getIdleTimeout();
|
||||
clone.maxTextMessageSize = this.getMaxTextMessageSize();
|
||||
clone.maxTextMessageBufferSize = this.getMaxTextMessageBufferSize();
|
||||
clone.maxBinaryMessageSize = this.getMaxBinaryMessageSize();
|
||||
clone.maxBinaryMessageBufferSize = this.getMaxBinaryMessageBufferSize();
|
||||
clone.inputBufferSize = this.getInputBufferSize() ;
|
||||
clone.asyncWriteTimeout = this.getAsyncWriteTimeout();
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a copy of the policy, with current values, but a different behavior.
|
||||
*
|
||||
* @param behavior the behavior to copy/clone
|
||||
* @return the cloned policy with a new behavior.
|
||||
* @deprecated use {@link #delegateAs(WebSocketBehavior)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public WebSocketPolicy clonePolicy(WebSocketBehavior behavior)
|
||||
{
|
||||
WebSocketPolicy clone = new WebSocketPolicy(behavior);
|
||||
clone.idleTimeout = this.idleTimeout;
|
||||
clone.maxTextMessageSize = this.maxTextMessageSize;
|
||||
clone.maxTextMessageBufferSize = this.maxTextMessageBufferSize;
|
||||
clone.maxBinaryMessageSize = this.maxBinaryMessageSize;
|
||||
clone.maxBinaryMessageBufferSize = this.maxBinaryMessageBufferSize;
|
||||
clone.inputBufferSize = this.inputBufferSize;
|
||||
clone.asyncWriteTimeout = this.asyncWriteTimeout;
|
||||
return clone;
|
||||
return delegateAs(behavior);
|
||||
}
|
||||
|
||||
public WebSocketPolicy delegateAs(WebSocketBehavior behavior)
|
||||
{
|
||||
if(behavior == this.behavior)
|
||||
return this;
|
||||
|
||||
return new WebSocketPolicy.Delegated(this, behavior);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -369,16 +389,152 @@ public class WebSocketPolicy
|
|||
public String toString()
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("WebSocketPolicy@").append(Integer.toHexString(hashCode()));
|
||||
builder.append("[behavior=").append(behavior);
|
||||
builder.append(",maxTextMessageSize=").append(maxTextMessageSize);
|
||||
builder.append(",maxTextMessageBufferSize=").append(maxTextMessageBufferSize);
|
||||
builder.append(",maxBinaryMessageSize=").append(maxBinaryMessageSize);
|
||||
builder.append(",maxBinaryMessageBufferSize=").append(maxBinaryMessageBufferSize);
|
||||
builder.append(",asyncWriteTimeout=").append(asyncWriteTimeout);
|
||||
builder.append(",idleTimeout=").append(idleTimeout);
|
||||
builder.append(",inputBufferSize=").append(inputBufferSize);
|
||||
builder.append(this.getClass().getSimpleName());
|
||||
builder.append("@").append(Integer.toHexString(hashCode()));
|
||||
builder.append("[behavior=").append(getBehavior());
|
||||
builder.append(",maxTextMessageSize=").append(getMaxTextMessageSize());
|
||||
builder.append(",maxTextMessageBufferSize=").append(getMaxTextMessageBufferSize());
|
||||
builder.append(",maxBinaryMessageSize=").append(getMaxBinaryMessageSize());
|
||||
builder.append(",maxBinaryMessageBufferSize=").append(getMaxTextMessageBufferSize());
|
||||
builder.append(",asyncWriteTimeout=").append(getAsyncWriteTimeout());
|
||||
builder.append(",idleTimeout=").append(getIdleTimeout());
|
||||
builder.append(",inputBufferSize=").append(getInputBufferSize());
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows Behavior to be changed, but the settings to delegated.
|
||||
* <p>
|
||||
* This rears its ugly head when a JSR356 Server Container is used as a
|
||||
* JSR356 Client Container.
|
||||
* The JSR356 Server Container is Behavior SERVER, but its container
|
||||
* level Policy is shared with the JSR356 Client Container as well.
|
||||
* This allows a delegate to the policy with a different behavior.
|
||||
* </p>
|
||||
*/
|
||||
private class Delegated extends WebSocketPolicy
|
||||
{
|
||||
private final WebSocketPolicy delegated;
|
||||
|
||||
public Delegated(WebSocketPolicy policy, WebSocketBehavior behavior)
|
||||
{
|
||||
super(behavior);
|
||||
this.delegated = policy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertValidBinaryMessageSize(int requestedSize)
|
||||
{
|
||||
delegated.assertValidBinaryMessageSize(requestedSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertValidTextMessageSize(int requestedSize)
|
||||
{
|
||||
delegated.assertValidTextMessageSize(requestedSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebSocketPolicy clonePolicy()
|
||||
{
|
||||
return delegated.clonePolicy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebSocketPolicy clonePolicy(WebSocketBehavior behavior)
|
||||
{
|
||||
return delegated.clonePolicy(behavior);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebSocketPolicy delegateAs(WebSocketBehavior behavior)
|
||||
{
|
||||
return delegated.delegateAs(behavior);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAsyncWriteTimeout()
|
||||
{
|
||||
return delegated.getAsyncWriteTimeout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getIdleTimeout()
|
||||
{
|
||||
return delegated.getIdleTimeout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInputBufferSize()
|
||||
{
|
||||
return delegated.getInputBufferSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxBinaryMessageBufferSize()
|
||||
{
|
||||
return delegated.getMaxBinaryMessageBufferSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxBinaryMessageSize()
|
||||
{
|
||||
return delegated.getMaxBinaryMessageSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxTextMessageBufferSize()
|
||||
{
|
||||
return delegated.getMaxTextMessageBufferSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxTextMessageSize()
|
||||
{
|
||||
return delegated.getMaxTextMessageSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAsyncWriteTimeout(long ms)
|
||||
{
|
||||
delegated.setAsyncWriteTimeout(ms);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdleTimeout(long ms)
|
||||
{
|
||||
delegated.setIdleTimeout(ms);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInputBufferSize(int size)
|
||||
{
|
||||
delegated.setInputBufferSize(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxBinaryMessageBufferSize(int size)
|
||||
{
|
||||
delegated.setMaxBinaryMessageBufferSize(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxBinaryMessageSize(int size)
|
||||
{
|
||||
delegated.setMaxBinaryMessageSize(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxTextMessageBufferSize(int size)
|
||||
{
|
||||
delegated.setMaxTextMessageBufferSize(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxTextMessageSize(int size)
|
||||
{
|
||||
delegated.setMaxTextMessageSize(size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -269,7 +269,7 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
|
|||
}
|
||||
|
||||
// Ensure we get a Client version of the policy.
|
||||
this.policy = scope.getPolicy().clonePolicy(WebSocketBehavior.CLIENT);
|
||||
this.policy = scope.getPolicy().delegateAs(WebSocketBehavior.CLIENT);
|
||||
// Support Late Binding of Object Factory (for CDI)
|
||||
this.objectFactorySupplier = () -> scope.getObjectFactory();
|
||||
this.extensionRegistry = new WebSocketExtensionFactory(this);
|
||||
|
|
|
@ -72,7 +72,6 @@ public class Parser
|
|||
private ByteBuffer payload;
|
||||
private int payloadLength;
|
||||
private PayloadProcessor maskProcessor = new DeMaskProcessor();
|
||||
// private PayloadProcessor strictnessProcessor;
|
||||
|
||||
/**
|
||||
* Is there an extension using RSV flag?
|
||||
|
|
Loading…
Reference in New Issue