Issue #3478 - changes from review
ExtensionStack.negotiate now differentiates between incorrect extension config offered or incorrect config from negotiation adding more BadMessageException cases Signed-off-by: lachan-roberts <lachlan@webtide.com>
This commit is contained in:
parent
eb4f7c000f
commit
0d570dd6b6
|
@ -156,18 +156,10 @@ public class JavaxWebSocketClientContainer extends JavaxWebSocketContainer imple
|
|||
upgradeRequest.addListener(jsrUpgradeListener);
|
||||
|
||||
for (Extension ext : clientEndpointConfig.getExtensions())
|
||||
{
|
||||
if (!getExtensionRegistry().isAvailable(ext.getName()))
|
||||
{
|
||||
throw new IllegalArgumentException("Requested extension [" + ext.getName() + "] is not installed");
|
||||
}
|
||||
upgradeRequest.addExtensions(new JavaxWebSocketExtensionConfig(ext));
|
||||
}
|
||||
|
||||
if (clientEndpointConfig.getPreferredSubprotocols().size() > 0)
|
||||
{
|
||||
upgradeRequest.setSubProtocols(clientEndpointConfig.getPreferredSubprotocols());
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
# org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.Slf4jLog
|
||||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
||||
org.eclipse.jetty.LEVEL=WARN
|
||||
org.eclipse.jetty.websocket.tests.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.websocket.tests.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.util.log.stderr.LONG=true
|
||||
# org.eclipse.jetty.server.AbstractConnector.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.io.WriteFlusher.LEVEL=DEBUG
|
||||
|
|
|
@ -260,7 +260,7 @@ public abstract class ClientUpgradeRequest extends HttpRequest implements Respon
|
|||
throw new HttpResponseException("Invalid Sec-WebSocket-Accept hash (was:" + respHash + ", expected:" + expectedHash + ")", response);
|
||||
|
||||
// Parse the Negotiated Extensions
|
||||
List<ExtensionConfig> extensions = new ArrayList<>();
|
||||
List<ExtensionConfig> negotiatedExtensions = new ArrayList<>();
|
||||
HttpField extField = response.getHeaders().getField(HttpHeader.SEC_WEBSOCKET_EXTENSIONS);
|
||||
if (extField != null)
|
||||
{
|
||||
|
@ -272,7 +272,7 @@ public abstract class ClientUpgradeRequest extends HttpRequest implements Respon
|
|||
QuotedStringTokenizer tok = new QuotedStringTokenizer(extVal, ",");
|
||||
while (tok.hasMoreTokens())
|
||||
{
|
||||
extensions.add(ExtensionConfig.parse(tok.nextToken()));
|
||||
negotiatedExtensions.add(ExtensionConfig.parse(tok.nextToken()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ public abstract class ClientUpgradeRequest extends HttpRequest implements Respon
|
|||
|
||||
// Verify the Negotiated Extensions
|
||||
List<ExtensionConfig> offeredExtensions = getExtensions();
|
||||
for (ExtensionConfig config : extensions)
|
||||
for (ExtensionConfig config : negotiatedExtensions)
|
||||
{
|
||||
if (config.getName().startsWith("@"))
|
||||
continue;
|
||||
|
@ -289,7 +289,7 @@ public abstract class ClientUpgradeRequest extends HttpRequest implements Respon
|
|||
if (numMatch < 1)
|
||||
throw new WebSocketException("Upgrade failed: Sec-WebSocket-Extensions contained extension not requested");
|
||||
|
||||
numMatch = extensions.stream().filter(c -> config.getName().equalsIgnoreCase(c.getName())).count();
|
||||
numMatch = negotiatedExtensions.stream().filter(c -> config.getName().equalsIgnoreCase(c.getName())).count();
|
||||
if (numMatch > 1)
|
||||
throw new WebSocketException("Upgrade failed: Sec-WebSocket-Extensions contained more than one extension of the same name");
|
||||
}
|
||||
|
@ -297,7 +297,7 @@ public abstract class ClientUpgradeRequest extends HttpRequest implements Respon
|
|||
// Negotiate the extension stack
|
||||
HttpClient httpClient = wsClient.getHttpClient();
|
||||
ExtensionStack extensionStack = new ExtensionStack(wsClient.getExtensionRegistry());
|
||||
extensionStack.negotiate(wsClient.getObjectFactory(), httpClient.getByteBufferPool(), extensions);
|
||||
extensionStack.negotiate(wsClient.getObjectFactory(), httpClient.getByteBufferPool(), offeredExtensions, negotiatedExtensions);
|
||||
|
||||
// Get the negotiated subprotocol
|
||||
String negotiatedSubProtocol = null;
|
||||
|
|
|
@ -87,11 +87,7 @@ public class WebSocketCoreClient extends ContainerLifeCycle implements FrameHand
|
|||
public CompletableFuture<FrameHandler.CoreSession> connect(ClientUpgradeRequest request) throws IOException
|
||||
{
|
||||
if (!isStarted())
|
||||
{
|
||||
throw new IllegalStateException(WebSocketCoreClient.class.getSimpleName() + "@" + this.hashCode() + " is not started");
|
||||
}
|
||||
|
||||
// TODO: add HttpClient delayed/on-demand start - See Issue #1516
|
||||
|
||||
// Validate Requested Extensions
|
||||
for (ExtensionConfig reqExt : request.getExtensions())
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.util.List;
|
|||
import java.util.ListIterator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jetty.http.BadMessageException;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.DecoratedObjectFactory;
|
||||
|
@ -38,6 +39,7 @@ import org.eclipse.jetty.websocket.core.ExtensionConfig;
|
|||
import org.eclipse.jetty.websocket.core.Frame;
|
||||
import org.eclipse.jetty.websocket.core.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.core.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.core.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.core.WebSocketExtensionRegistry;
|
||||
|
||||
/**
|
||||
|
@ -107,20 +109,37 @@ public class ExtensionStack implements IncomingFrames, OutgoingFrames, Dumpable
|
|||
* <p>
|
||||
* For the list of negotiated extensions, use {@link #getNegotiatedExtensions()}
|
||||
*
|
||||
* @param configs the configurations being requested
|
||||
* @param offeredConfigs the configurations being requested by the client
|
||||
* @param negotiatedConfigs the configurations accepted by the server
|
||||
*/
|
||||
public void negotiate(DecoratedObjectFactory objectFactory, ByteBufferPool bufferPool, List<ExtensionConfig> configs)
|
||||
public void negotiate(DecoratedObjectFactory objectFactory, ByteBufferPool bufferPool, List<ExtensionConfig> offeredConfigs, List<ExtensionConfig> negotiatedConfigs)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Extension Configs={}", configs);
|
||||
LOG.debug("Extension Configs={}", negotiatedConfigs);
|
||||
|
||||
this.extensions = new ArrayList<>();
|
||||
|
||||
String rsvClaims[] = new String[3];
|
||||
|
||||
for (ExtensionConfig config : configs)
|
||||
for (ExtensionConfig config : negotiatedConfigs)
|
||||
{
|
||||
Extension ext = factory.newInstance(objectFactory, bufferPool, config);
|
||||
Extension ext;
|
||||
|
||||
try
|
||||
{
|
||||
ext = factory.newInstance(objectFactory, bufferPool, config);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
for (ExtensionConfig offered : offeredConfigs)
|
||||
{
|
||||
if (offered.getParameterizedName().equals(config.getParameterizedName()))
|
||||
throw new BadMessageException("offered extension had bad parameters: ", t);
|
||||
}
|
||||
|
||||
throw new WebSocketException("negotiated extension had bad parameters: ", t);
|
||||
}
|
||||
|
||||
if (ext == null)
|
||||
{
|
||||
// Extension not present on this side
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.stream.Collectors;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.BadMessageException;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.QuotedCSV;
|
||||
|
@ -55,13 +56,16 @@ public class Negotiation
|
|||
private String subprotocol;
|
||||
private ExtensionStack extensionStack;
|
||||
|
||||
/**
|
||||
* @throws BadMessageException if there is any errors parsing the upgrade request
|
||||
*/
|
||||
public Negotiation(
|
||||
Request baseRequest,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
WebSocketExtensionRegistry registry,
|
||||
DecoratedObjectFactory objectFactory,
|
||||
ByteBufferPool bufferPool)
|
||||
ByteBufferPool bufferPool) throws BadMessageException
|
||||
{
|
||||
this.baseRequest = baseRequest;
|
||||
this.request = request;
|
||||
|
@ -77,73 +81,80 @@ public class Negotiation
|
|||
QuotedCSV extensions = null;
|
||||
QuotedCSV subprotocols = null;
|
||||
|
||||
for (HttpField field : baseRequest.getHttpFields())
|
||||
try
|
||||
{
|
||||
if (field.getHeader() != null)
|
||||
for (HttpField field : baseRequest.getHttpFields())
|
||||
{
|
||||
switch (field.getHeader())
|
||||
if (field.getHeader() != null)
|
||||
{
|
||||
case UPGRADE:
|
||||
if (upgrade == null && "websocket".equalsIgnoreCase(field.getValue()))
|
||||
upgrade = Boolean.TRUE;
|
||||
break;
|
||||
switch (field.getHeader())
|
||||
{
|
||||
case UPGRADE:
|
||||
if (upgrade == null && "websocket".equalsIgnoreCase(field.getValue()))
|
||||
upgrade = Boolean.TRUE;
|
||||
break;
|
||||
|
||||
case CONNECTION:
|
||||
if (connectionCSVs == null)
|
||||
connectionCSVs = new QuotedCSV();
|
||||
connectionCSVs.addValue(field.getValue());
|
||||
break;
|
||||
case CONNECTION:
|
||||
if (connectionCSVs == null)
|
||||
connectionCSVs = new QuotedCSV();
|
||||
connectionCSVs.addValue(field.getValue());
|
||||
break;
|
||||
|
||||
case SEC_WEBSOCKET_KEY:
|
||||
key = field.getValue();
|
||||
break;
|
||||
case SEC_WEBSOCKET_KEY:
|
||||
key = field.getValue();
|
||||
break;
|
||||
|
||||
case SEC_WEBSOCKET_VERSION:
|
||||
version = field.getValue();
|
||||
break;
|
||||
case SEC_WEBSOCKET_VERSION:
|
||||
version = field.getValue();
|
||||
break;
|
||||
|
||||
case SEC_WEBSOCKET_EXTENSIONS:
|
||||
if (extensions == null)
|
||||
extensions = new QuotedCSV(field.getValue());
|
||||
else
|
||||
extensions.addValue(field.getValue());
|
||||
break;
|
||||
case SEC_WEBSOCKET_EXTENSIONS:
|
||||
if (extensions == null)
|
||||
extensions = new QuotedCSV(field.getValue());
|
||||
else
|
||||
extensions.addValue(field.getValue());
|
||||
break;
|
||||
|
||||
case SEC_WEBSOCKET_SUBPROTOCOL:
|
||||
if (subprotocols == null)
|
||||
subprotocols = new QuotedCSV(field.getValue());
|
||||
else
|
||||
subprotocols.addValue(field.getValue());
|
||||
break;
|
||||
case SEC_WEBSOCKET_SUBPROTOCOL:
|
||||
if (subprotocols == null)
|
||||
subprotocols = new QuotedCSV(field.getValue());
|
||||
else
|
||||
subprotocols.addValue(field.getValue());
|
||||
break;
|
||||
|
||||
default:
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.version = version;
|
||||
this.key = key;
|
||||
this.upgrade = upgrade != null && connectionCSVs != null && connectionCSVs.getValues().stream().anyMatch(s -> s.equalsIgnoreCase("Upgrade"));
|
||||
|
||||
Set<String> available = registry.getAvailableExtensionNames();
|
||||
offeredExtensions = extensions == null
|
||||
? Collections.emptyList()
|
||||
: extensions.getValues().stream()
|
||||
.map(ExtensionConfig::parse)
|
||||
.filter(ec -> available.contains(ec.getName().toLowerCase()) && !ec.getName().startsWith("@"))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
offeredSubprotocols = subprotocols == null
|
||||
? Collections.emptyList()
|
||||
: subprotocols.getValues();
|
||||
|
||||
negotiatedExtensions = new ArrayList<>();
|
||||
for (ExtensionConfig config : offeredExtensions)
|
||||
{
|
||||
long matches = negotiatedExtensions.stream()
|
||||
.filter(negotiatedConfig -> negotiatedConfig.getName().equals(config.getName())).count();
|
||||
if (matches == 0)
|
||||
negotiatedExtensions.add(config);
|
||||
}
|
||||
}
|
||||
|
||||
this.version = version;
|
||||
this.key = key;
|
||||
this.upgrade = upgrade != null && connectionCSVs != null && connectionCSVs.getValues().stream().anyMatch(s -> s.equalsIgnoreCase("Upgrade"));
|
||||
|
||||
Set<String> available = registry.getAvailableExtensionNames();
|
||||
offeredExtensions = extensions == null
|
||||
?Collections.emptyList()
|
||||
:extensions.getValues().stream()
|
||||
.map(ExtensionConfig::parse)
|
||||
.filter(ec -> available.contains(ec.getName().toLowerCase()) && !ec.getName().startsWith("@"))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
offeredSubprotocols = subprotocols == null
|
||||
?Collections.emptyList()
|
||||
:subprotocols.getValues();
|
||||
|
||||
negotiatedExtensions = new ArrayList<>();
|
||||
for (ExtensionConfig config : offeredExtensions)
|
||||
catch (Throwable t)
|
||||
{
|
||||
long matches = negotiatedExtensions.stream()
|
||||
.filter(negotiatedConfig->negotiatedConfig.getName().equals(config.getName())).count();
|
||||
if (matches == 0)
|
||||
negotiatedExtensions.add(config);
|
||||
throw new BadMessageException("Invalid Handshake Request", t);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,7 +228,7 @@ public class Negotiation
|
|||
{
|
||||
// Extension stack can decide to drop any of these extensions or their parameters
|
||||
extensionStack = new ExtensionStack(registry);
|
||||
extensionStack.negotiate(objectFactory, bufferPool, negotiatedExtensions);
|
||||
extensionStack.negotiate(objectFactory, bufferPool, offeredExtensions, negotiatedExtensions);
|
||||
negotiatedExtensions = extensionStack.getNegotiatedExtensions();
|
||||
|
||||
if (extensionStack.hasNegotiatedExtensions())
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.concurrent.Executor;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.BadMessageException;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
|
@ -47,6 +48,7 @@ import org.eclipse.jetty.websocket.core.ExtensionConfig;
|
|||
import org.eclipse.jetty.websocket.core.FrameHandler;
|
||||
import org.eclipse.jetty.websocket.core.WebSocketConstants;
|
||||
import org.eclipse.jetty.websocket.core.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.core.internal.ExtensionStack;
|
||||
import org.eclipse.jetty.websocket.core.internal.Negotiated;
|
||||
import org.eclipse.jetty.websocket.core.internal.WebSocketChannel;
|
||||
import org.eclipse.jetty.websocket.core.internal.WebSocketConnection;
|
||||
|
@ -119,11 +121,7 @@ public final class RFC6455Handshaker implements Handshaker
|
|||
}
|
||||
|
||||
if (negotiation.getKey() == null)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("not upgraded no key {}", baseRequest);
|
||||
return false;
|
||||
}
|
||||
throw new BadMessageException("not upgraded no key");
|
||||
|
||||
// Negotiate the FrameHandler
|
||||
FrameHandler handler = negotiator.negotiate(negotiation);
|
||||
|
@ -150,7 +148,8 @@ public final class RFC6455Handshaker implements Handshaker
|
|||
// Check for handler
|
||||
if (handler == null)
|
||||
{
|
||||
LOG.warn("not upgraded: no frame handler provided {}", baseRequest);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("not upgraded: no frame handler provided {}", baseRequest);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -182,11 +181,14 @@ public final class RFC6455Handshaker implements Handshaker
|
|||
throw new WebSocketException("Upgrade failed: multiple negotiated extensions of the same name");
|
||||
}
|
||||
|
||||
// Create and Negotiate the ExtensionStack
|
||||
ExtensionStack extensionStack = negotiation.getExtensionStack();
|
||||
|
||||
Negotiated negotiated = new Negotiated(
|
||||
baseRequest.getHttpURI().toURI(),
|
||||
subprotocol,
|
||||
baseRequest.isSecure(),
|
||||
negotiation.getExtensionStack(),
|
||||
extensionStack,
|
||||
WebSocketConstants.SPEC_VERSION_STRING);
|
||||
|
||||
// Create the Channel
|
||||
|
@ -203,10 +205,7 @@ public final class RFC6455Handshaker implements Handshaker
|
|||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("connection {}", connection);
|
||||
if (connection == null)
|
||||
{
|
||||
LOG.warn("not upgraded: no connection {}", baseRequest);
|
||||
return false;
|
||||
}
|
||||
throw new WebSocketException("not upgraded: no connection");
|
||||
|
||||
for (Connection.Listener listener : connector.getBeans(Connection.Listener.class))
|
||||
connection.addListener(listener);
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.core;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.LinkedList;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.util.DecoratedObjectFactory;
|
||||
|
@ -29,10 +33,6 @@ import org.junit.jupiter.params.ParameterizedTest;
|
|||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.LinkedList;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
/**
|
||||
|
@ -64,7 +64,7 @@ public class GeneratorFrameFlagsTest
|
|||
public void setup(Frame invalidFrame)
|
||||
{
|
||||
ExtensionStack exStack = new ExtensionStack(new WebSocketExtensionRegistry());
|
||||
exStack.negotiate(new DecoratedObjectFactory(), bufferPool, new LinkedList<>());
|
||||
exStack.negotiate(new DecoratedObjectFactory(), bufferPool, new LinkedList<>(), new LinkedList<>());
|
||||
this.channel = new WebSocketChannel(new AbstractTestFrameHandler(), Behavior.CLIENT, Negotiated.from(exStack));
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ public class GeneratorTest
|
|||
{
|
||||
ByteBufferPool bufferPool = new MappedByteBufferPool();
|
||||
ExtensionStack exStack = new ExtensionStack(new WebSocketExtensionRegistry());
|
||||
exStack.negotiate(new DecoratedObjectFactory(), bufferPool, new LinkedList<>());
|
||||
exStack.negotiate(new DecoratedObjectFactory(), bufferPool, new LinkedList<>(), new LinkedList<>());
|
||||
return new WebSocketChannel(new AbstractTestFrameHandler(), behavior, Negotiated.from(exStack));
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ public class ParserCapture
|
|||
|
||||
ByteBufferPool bufferPool = new MappedByteBufferPool();
|
||||
ExtensionStack exStack = new ExtensionStack(new WebSocketExtensionRegistry());
|
||||
exStack.negotiate(new DecoratedObjectFactory(), bufferPool, new LinkedList<>());
|
||||
exStack.negotiate(new DecoratedObjectFactory(), bufferPool, new LinkedList<>(), new LinkedList<>());
|
||||
this.channel = new WebSocketChannel(new AbstractTestFrameHandler(), behavior, Negotiated.from(exStack));
|
||||
}
|
||||
|
||||
|
|
|
@ -420,7 +420,7 @@ public class DeflateFrameExtensionTest extends AbstractExtensionTest
|
|||
{
|
||||
ByteBufferPool bufferPool = new MappedByteBufferPool();
|
||||
ExtensionStack exStack = new ExtensionStack(new WebSocketExtensionRegistry());
|
||||
exStack.negotiate(new DecoratedObjectFactory(), bufferPool, new LinkedList<>());
|
||||
exStack.negotiate(new DecoratedObjectFactory(), bufferPool, new LinkedList<>(), new LinkedList<>());
|
||||
|
||||
WebSocketChannel channel = new WebSocketChannel(new AbstractTestFrameHandler(), Behavior.SERVER, Negotiated.from(exStack));
|
||||
channel.setMaxFrameSize(maxMessageSize);
|
||||
|
|
|
@ -75,7 +75,7 @@ public class ExtensionStackTest
|
|||
// 1 extension
|
||||
List<ExtensionConfig> configs = new ArrayList<>();
|
||||
configs.add(ExtensionConfig.parse("identity"));
|
||||
stack.negotiate(objectFactory, bufferPool, configs);
|
||||
stack.negotiate(objectFactory, bufferPool, configs, configs);
|
||||
|
||||
// Setup Listeners
|
||||
IncomingFrames session = new IncomingFramesCapture();
|
||||
|
@ -99,7 +99,7 @@ public class ExtensionStackTest
|
|||
List<ExtensionConfig> configs = new ArrayList<>();
|
||||
configs.add(ExtensionConfig.parse("identity; id=A"));
|
||||
configs.add(ExtensionConfig.parse("identity; id=B"));
|
||||
stack.negotiate(objectFactory, bufferPool, configs);
|
||||
stack.negotiate(objectFactory, bufferPool, configs, configs);
|
||||
|
||||
// Setup Listeners
|
||||
IncomingFrames session = new IncomingFramesCapture();
|
||||
|
@ -130,7 +130,7 @@ public class ExtensionStackTest
|
|||
{
|
||||
String chromeRequest = "permessage-deflate; client_max_window_bits, x-webkit-deflate-frame";
|
||||
List<ExtensionConfig> requestedConfigs = ExtensionConfig.parseList(chromeRequest);
|
||||
stack.negotiate(objectFactory, bufferPool, requestedConfigs);
|
||||
stack.negotiate(objectFactory, bufferPool, requestedConfigs, requestedConfigs);
|
||||
|
||||
List<ExtensionConfig> negotiated = stack.getNegotiatedExtensions();
|
||||
String response = ExtensionConfig.toHeaderValue(negotiated);
|
||||
|
|
|
@ -154,7 +154,7 @@ public class ExtensionTool
|
|||
{
|
||||
ByteBufferPool bufferPool = new MappedByteBufferPool();
|
||||
ExtensionStack exStack = new ExtensionStack(new WebSocketExtensionRegistry());
|
||||
exStack.negotiate(new DecoratedObjectFactory(), bufferPool, new LinkedList<>());
|
||||
exStack.negotiate(new DecoratedObjectFactory(), bufferPool, new LinkedList<>(), new LinkedList<>());
|
||||
WebSocketChannel channel = new WebSocketChannel(new AbstractTestFrameHandler(), Behavior.SERVER, Negotiated.from(exStack));
|
||||
return channel;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ import java.net.HttpCookie;
|
|||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.security.Principal;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
|
@ -38,6 +37,7 @@ import javax.servlet.http.Cookie;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.eclipse.jetty.http.BadMessageException;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.websocket.core.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.core.WebSocketConstants;
|
||||
|
@ -57,21 +57,28 @@ public class ServletUpgradeRequest
|
|||
private List<HttpCookie> cookies;
|
||||
private Map<String, List<String>> parameterMap;
|
||||
|
||||
public ServletUpgradeRequest(Negotiation negotiation) throws URISyntaxException
|
||||
public ServletUpgradeRequest(Negotiation negotiation) throws BadMessageException
|
||||
{
|
||||
this.negotiation = negotiation;
|
||||
HttpServletRequest httpRequest = negotiation.getRequest();
|
||||
this.queryString = httpRequest.getQueryString();
|
||||
this.secure = httpRequest.isSecure();
|
||||
|
||||
// TODO why is this URL and not URI?
|
||||
StringBuffer uri = httpRequest.getRequestURL();
|
||||
// WHY?
|
||||
if (this.queryString != null)
|
||||
uri.append("?").append(this.queryString);
|
||||
uri.replace(0, uri.indexOf(":"), secure?"wss":"ws");
|
||||
this.requestURI = new URI(uri.toString());
|
||||
this.request = new UpgradeHttpServletRequest(httpRequest);
|
||||
try
|
||||
{
|
||||
// TODO why is this URL and not URI?
|
||||
StringBuffer uri = httpRequest.getRequestURL();
|
||||
// WHY?
|
||||
if (this.queryString != null)
|
||||
uri.append("?").append(this.queryString);
|
||||
uri.replace(0, uri.indexOf(":"), secure ? "wss" : "ws");
|
||||
this.requestURI = new URI(uri.toString());
|
||||
this.request = new UpgradeHttpServletRequest(httpRequest);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
throw new BadMessageException("Bad WebSocket UpgradeRequest", t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
package org.eclipse.jetty.websocket.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
@ -32,7 +31,6 @@ import org.eclipse.jetty.http.pathmap.PathSpec;
|
|||
import org.eclipse.jetty.http.pathmap.RegexPathSpec;
|
||||
import org.eclipse.jetty.http.pathmap.ServletPathSpec;
|
||||
import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec;
|
||||
import org.eclipse.jetty.io.RuntimeIOException;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.util.component.Dumpable;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
|
@ -217,7 +215,7 @@ public class WebSocketMapping implements Dumpable, LifeCycle.Listener
|
|||
return mapping.getResource();
|
||||
}
|
||||
|
||||
public boolean upgrade(HttpServletRequest request, HttpServletResponse response, FrameHandler.Customizer defaultCustomizer)
|
||||
public boolean upgrade(HttpServletRequest request, HttpServletResponse response, FrameHandler.Customizer defaultCustomizer) throws IOException
|
||||
{
|
||||
// Since this may be a filter, we need to be smart about determining the target path.
|
||||
// We should rely on the Container for stripping path parameters and its ilk before
|
||||
|
@ -240,14 +238,7 @@ public class WebSocketMapping implements Dumpable, LifeCycle.Listener
|
|||
LOG.debug("WebSocket Negotiated detected on {} for endpoint {}", target, negotiator);
|
||||
|
||||
// We have an upgrade request
|
||||
try
|
||||
{
|
||||
return handshaker.upgradeRequest(negotiator, request, response, defaultCustomizer);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new WebSocketException(e);
|
||||
}
|
||||
return handshaker.upgradeRequest(negotiator, request, response, defaultCustomizer);
|
||||
}
|
||||
|
||||
private class Negotiator extends WebSocketNegotiator.AbstractNegotiator
|
||||
|
@ -269,7 +260,7 @@ public class WebSocketMapping implements Dumpable, LifeCycle.Listener
|
|||
|
||||
|
||||
@Override
|
||||
public FrameHandler negotiate(Negotiation negotiation)
|
||||
public FrameHandler negotiate(Negotiation negotiation) throws IOException
|
||||
{
|
||||
ServletContext servletContext = negotiation.getRequest().getServletContext();
|
||||
if (servletContext == null)
|
||||
|
@ -304,14 +295,6 @@ public class WebSocketMapping implements Dumpable, LifeCycle.Listener
|
|||
|
||||
return null;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeIOException(e);
|
||||
}
|
||||
catch (URISyntaxException e)
|
||||
{
|
||||
throw new RuntimeIOException("Unable to negotiate websocket due to mangled request URI", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Thread.currentThread().setContextClassLoader(old);
|
||||
|
|
Loading…
Reference in New Issue