444771 - JSR356 / EndPointConfig.userProperties are not unique per
endpoint upgrade + Adding testcase & implementation which honors the ServerEndpointConfig.userProperties copy at an earlier point.
This commit is contained in:
parent
b633778b33
commit
1ce66f38a0
|
@ -54,14 +54,14 @@ public class BasicServerEndpointConfig implements ServerEndpointConfig
|
||||||
|
|
||||||
public BasicServerEndpointConfig(ServerEndpointConfig copy)
|
public BasicServerEndpointConfig(ServerEndpointConfig copy)
|
||||||
{
|
{
|
||||||
|
// immutable concepts
|
||||||
this.endpointClass = copy.getEndpointClass();
|
this.endpointClass = copy.getEndpointClass();
|
||||||
this.path = copy.getPath();
|
this.path = copy.getPath();
|
||||||
|
|
||||||
this.decoders = new ArrayList<>(copy.getDecoders());
|
this.decoders = copy.getDecoders();
|
||||||
this.encoders = new ArrayList<>(copy.getEncoders());
|
this.encoders = copy.getEncoders();
|
||||||
this.subprotocols = new ArrayList<>(copy.getSubprotocols());
|
this.subprotocols = copy.getSubprotocols();
|
||||||
this.extensions = new ArrayList<>(copy.getExtensions());
|
this.extensions = copy.getExtensions();
|
||||||
this.userProperties = new HashMap<>(copy.getUserProperties());
|
|
||||||
if (copy.getConfigurator() != null)
|
if (copy.getConfigurator() != null)
|
||||||
{
|
{
|
||||||
this.configurator = copy.getConfigurator();
|
this.configurator = copy.getConfigurator();
|
||||||
|
@ -70,6 +70,9 @@ public class BasicServerEndpointConfig implements ServerEndpointConfig
|
||||||
{
|
{
|
||||||
this.configurator = BasicServerEndpointConfigurator.INSTANCE;
|
this.configurator = BasicServerEndpointConfigurator.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mutable concepts
|
||||||
|
this.userProperties = new HashMap<>(copy.getUserProperties());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -56,8 +56,14 @@ public class JsrCreator implements WebSocketCreator
|
||||||
JsrHandshakeRequest hsreq = new JsrHandshakeRequest(req);
|
JsrHandshakeRequest hsreq = new JsrHandshakeRequest(req);
|
||||||
JsrHandshakeResponse hsresp = new JsrHandshakeResponse(resp);
|
JsrHandshakeResponse hsresp = new JsrHandshakeResponse(resp);
|
||||||
|
|
||||||
|
// Get raw config, as defined when the endpoint was added to the container
|
||||||
ServerEndpointConfig config = metadata.getConfig();
|
ServerEndpointConfig config = metadata.getConfig();
|
||||||
|
|
||||||
|
// Establish a copy of the config, so that the UserProperties are unique
|
||||||
|
// per upgrade request.
|
||||||
|
config = new BasicServerEndpointConfig(config);
|
||||||
|
|
||||||
|
// Get Configurator from config object (not guaranteed to be unique per endpoint upgrade)
|
||||||
ServerEndpointConfig.Configurator configurator = config.getConfigurator();
|
ServerEndpointConfig.Configurator configurator = config.getConfigurator();
|
||||||
|
|
||||||
// modify handshake
|
// modify handshake
|
||||||
|
|
|
@ -18,12 +18,16 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.websocket.jsr356.server;
|
package org.eclipse.jetty.websocket.jsr356.server;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import javax.websocket.Extension;
|
import javax.websocket.Extension;
|
||||||
import javax.websocket.HandshakeResponse;
|
import javax.websocket.HandshakeResponse;
|
||||||
import javax.websocket.OnMessage;
|
import javax.websocket.OnMessage;
|
||||||
|
@ -49,9 +53,6 @@ import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.is;
|
|
||||||
import static org.hamcrest.Matchers.nullValue;
|
|
||||||
|
|
||||||
public class ConfiguratorTest
|
public class ConfiguratorTest
|
||||||
{
|
{
|
||||||
private static final Logger LOG = Log.getLogger(ConfiguratorTest.class);
|
private static final Logger LOG = Log.getLogger(ConfiguratorTest.class);
|
||||||
|
@ -161,6 +162,48 @@ public class ConfiguratorTest
|
||||||
return response.toString();
|
return response.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class UniqueUserPropsConfigurator extends ServerEndpointConfig.Configurator
|
||||||
|
{
|
||||||
|
private AtomicInteger upgradeCount = new AtomicInteger(0);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response)
|
||||||
|
{
|
||||||
|
int upgradeNum = upgradeCount.addAndGet(1);
|
||||||
|
LOG.debug("Upgrade Num: {}", upgradeNum);
|
||||||
|
sec.getUserProperties().put("upgradeNum",Integer.toString(upgradeNum));
|
||||||
|
switch(upgradeNum) {
|
||||||
|
case 1: sec.getUserProperties().put("apple", "fruit from tree"); break;
|
||||||
|
case 2: sec.getUserProperties().put("blueberry", "fruit from bush"); break;
|
||||||
|
case 3: sec.getUserProperties().put("strawberry", "fruit from annual"); break;
|
||||||
|
default: sec.getUserProperties().put("fruit"+upgradeNum, "placeholder"); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.modifyHandshake(sec,request,response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ServerEndpoint(value = "/unique-user-props", configurator = UniqueUserPropsConfigurator.class)
|
||||||
|
public static class UniqueUserPropsSocket
|
||||||
|
{
|
||||||
|
@OnMessage
|
||||||
|
public String onMessage(Session session, String msg)
|
||||||
|
{
|
||||||
|
String value = (String)session.getUserProperties().get(msg);
|
||||||
|
StringBuilder response = new StringBuilder();
|
||||||
|
response.append("Requested User Property: [").append(msg).append("] = ");
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
response.append("<null>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response.append('"').append(value).append('"');
|
||||||
|
}
|
||||||
|
return response.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static Server server;
|
private static Server server;
|
||||||
private static URI baseServerUri;
|
private static URI baseServerUri;
|
||||||
|
@ -182,6 +225,7 @@ public class ConfiguratorTest
|
||||||
container.addEndpoint(EmptySocket.class);
|
container.addEndpoint(EmptySocket.class);
|
||||||
container.addEndpoint(NoExtensionsSocket.class);
|
container.addEndpoint(NoExtensionsSocket.class);
|
||||||
container.addEndpoint(ProtocolsSocket.class);
|
container.addEndpoint(ProtocolsSocket.class);
|
||||||
|
container.addEndpoint(UniqueUserPropsSocket.class);
|
||||||
|
|
||||||
server.start();
|
server.start();
|
||||||
String host = connector.getHost();
|
String host = connector.getHost();
|
||||||
|
@ -250,6 +294,43 @@ public class ConfiguratorTest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUniqueUserPropsConfigurator() throws Exception
|
||||||
|
{
|
||||||
|
URI uri = baseServerUri.resolve("/unique-user-props");
|
||||||
|
|
||||||
|
// First request
|
||||||
|
try (BlockheadClient client = new BlockheadClient(uri))
|
||||||
|
{
|
||||||
|
client.connect();
|
||||||
|
client.sendStandardRequest();
|
||||||
|
client.expectUpgradeResponse();
|
||||||
|
|
||||||
|
client.write(new TextFrame().setPayload("apple"));
|
||||||
|
EventQueue<WebSocketFrame> frames = client.readFrames(1,1,TimeUnit.SECONDS);
|
||||||
|
WebSocketFrame frame = frames.poll();
|
||||||
|
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested User Property: [apple] = \"fruit from tree\""));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second request
|
||||||
|
try (BlockheadClient client = new BlockheadClient(uri))
|
||||||
|
{
|
||||||
|
client.connect();
|
||||||
|
client.sendStandardRequest();
|
||||||
|
client.expectUpgradeResponse();
|
||||||
|
|
||||||
|
client.write(new TextFrame().setPayload("apple"));
|
||||||
|
client.write(new TextFrame().setPayload("blueberry"));
|
||||||
|
EventQueue<WebSocketFrame> frames = client.readFrames(2,1,TimeUnit.SECONDS);
|
||||||
|
WebSocketFrame frame = frames.poll();
|
||||||
|
// should have no value
|
||||||
|
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested User Property: [apple] = <null>"));
|
||||||
|
|
||||||
|
frame = frames.poll();
|
||||||
|
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested User Property: [blueberry] = \"fruit from bush\""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test of Sec-WebSocket-Protocol, as seen in RFC-6455, 1 protocol
|
* Test of Sec-WebSocket-Protocol, as seen in RFC-6455, 1 protocol
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue