433793 - WebSocket / empty protocol list in ServerEndpointConfig.Configurator when using non-exact header name
+ Marking header (and parameter) maps as case-insensitive.
This commit is contained in:
parent
8e957b5a23
commit
5635f02235
|
@ -25,6 +25,7 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.websocket.Extension;
|
||||
import javax.websocket.HandshakeResponse;
|
||||
|
@ -130,6 +131,38 @@ public class ConfiguratorTest
|
|||
}
|
||||
}
|
||||
|
||||
public static class ProtocolsConfigurator extends ServerEndpointConfig.Configurator
|
||||
{
|
||||
public static AtomicReference<String> seenProtocols = new AtomicReference<>();
|
||||
|
||||
@Override
|
||||
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response)
|
||||
{
|
||||
super.modifyHandshake(sec,request,response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNegotiatedSubprotocol(List<String> supported, List<String> requested)
|
||||
{
|
||||
LOG.warn(new Throwable());
|
||||
String seen = QuoteUtil.join(requested,",");
|
||||
seenProtocols.compareAndSet(null,seen);
|
||||
return super.getNegotiatedSubprotocol(supported,requested);
|
||||
}
|
||||
}
|
||||
|
||||
@ServerEndpoint(value = "/protocols", configurator = ProtocolsConfigurator.class)
|
||||
public static class ProtocolsSocket
|
||||
{
|
||||
@OnMessage
|
||||
public String onMessage(Session session, String msg)
|
||||
{
|
||||
StringBuilder response = new StringBuilder();
|
||||
response.append("Requested Protocols: [").append(ProtocolsConfigurator.seenProtocols.get()).append("]");
|
||||
return response.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static Server server;
|
||||
private static URI baseServerUri;
|
||||
|
||||
|
@ -149,6 +182,7 @@ public class ConfiguratorTest
|
|||
container.addEndpoint(CaptureHeadersSocket.class);
|
||||
container.addEndpoint(EmptySocket.class);
|
||||
container.addEndpoint(NoExtensionsSocket.class);
|
||||
container.addEndpoint(ProtocolsSocket.class);
|
||||
|
||||
server.start();
|
||||
String host = connector.getHost();
|
||||
|
@ -215,4 +249,96 @@ public class ConfiguratorTest
|
|||
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Request Header [X-Dummy]: \"Bogus\""));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of Sec-WebSocket-Protocol, as seen in RFC-6455, 1 protocol
|
||||
*/
|
||||
@Test
|
||||
public void testProtocol_Single() throws Exception
|
||||
{
|
||||
URI uri = baseServerUri.resolve("/protocols");
|
||||
ProtocolsConfigurator.seenProtocols.set(null);
|
||||
|
||||
try (BlockheadClient client = new BlockheadClient(uri))
|
||||
{
|
||||
client.addHeader("Sec-WebSocket-Protocol: echo\r\n");
|
||||
client.connect();
|
||||
client.sendStandardRequest();
|
||||
client.expectUpgradeResponse();
|
||||
|
||||
client.write(new TextFrame().setPayload("getProtocols"));
|
||||
EventQueue<WebSocketFrame> frames = client.readFrames(1,1,TimeUnit.SECONDS);
|
||||
WebSocketFrame frame = frames.poll();
|
||||
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\"]"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of Sec-WebSocket-Protocol, as seen in RFC-6455, 3 protocols
|
||||
*/
|
||||
@Test
|
||||
public void testProtocol_Triple() throws Exception
|
||||
{
|
||||
URI uri = baseServerUri.resolve("/protocols");
|
||||
ProtocolsConfigurator.seenProtocols.set(null);
|
||||
|
||||
try (BlockheadClient client = new BlockheadClient(uri))
|
||||
{
|
||||
client.addHeader("Sec-WebSocket-Protocol: echo, chat, status\r\n");
|
||||
client.connect();
|
||||
client.sendStandardRequest();
|
||||
client.expectUpgradeResponse();
|
||||
|
||||
client.write(new TextFrame().setPayload("getProtocols"));
|
||||
EventQueue<WebSocketFrame> frames = client.readFrames(1,1,TimeUnit.SECONDS);
|
||||
WebSocketFrame frame = frames.poll();
|
||||
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\",\"chat\",\"status\"]"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of Sec-WebSocket-Protocol, using all lowercase header
|
||||
*/
|
||||
@Test
|
||||
public void testProtocol_LowercaseHeader() throws Exception
|
||||
{
|
||||
URI uri = baseServerUri.resolve("/protocols");
|
||||
ProtocolsConfigurator.seenProtocols.set(null);
|
||||
|
||||
try (BlockheadClient client = new BlockheadClient(uri))
|
||||
{
|
||||
client.addHeader("sec-websocket-protocol: echo, chat, status\r\n");
|
||||
client.connect();
|
||||
client.sendStandardRequest();
|
||||
client.expectUpgradeResponse();
|
||||
|
||||
client.write(new TextFrame().setPayload("getProtocols"));
|
||||
EventQueue<WebSocketFrame> frames = client.readFrames(1,1,TimeUnit.SECONDS);
|
||||
WebSocketFrame frame = frames.poll();
|
||||
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\",\"chat\",\"status\"]"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of Sec-WebSocket-Protocol, using non-spec case header
|
||||
*/
|
||||
@Test
|
||||
public void testProtocol_AltHeaderCase() throws Exception
|
||||
{
|
||||
URI uri = baseServerUri.resolve("/protocols");
|
||||
ProtocolsConfigurator.seenProtocols.set(null);
|
||||
|
||||
try (BlockheadClient client = new BlockheadClient(uri))
|
||||
{
|
||||
client.addHeader("Sec-Websocket-Protocol: echo, chat, status\r\n");
|
||||
client.connect();
|
||||
client.sendStandardRequest();
|
||||
client.expectUpgradeResponse();
|
||||
|
||||
client.write(new TextFrame().setPayload("getProtocols"));
|
||||
EventQueue<WebSocketFrame> frames = client.readFrames(1,1,TimeUnit.SECONDS);
|
||||
WebSocketFrame frame = frames.poll();
|
||||
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\",\"chat\",\"status\"]"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ 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;
|
||||
|
@ -68,8 +70,8 @@ public class UpgradeHttpServletRequest implements HttpServletRequest
|
|||
private final String remoteUser;
|
||||
private final Principal principal;
|
||||
|
||||
private final Map<String, List<String>> headers = new HashMap<>(8);
|
||||
private final Map<String, String[]> parameters = new HashMap<>(2);
|
||||
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);
|
||||
private final Map<String, Object> attributes = new HashMap<>(2);
|
||||
private final List<Locale> locales = new ArrayList<>(2);
|
||||
|
||||
|
|
Loading…
Reference in New Issue