Issue #3465 - client/server error handling behavior for ExtensionStack
Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
parent
0d570dd6b6
commit
46ef94c1b9
|
@ -296,7 +296,7 @@ public abstract class ClientUpgradeRequest extends HttpRequest implements Respon
|
|||
|
||||
// Negotiate the extension stack
|
||||
HttpClient httpClient = wsClient.getHttpClient();
|
||||
ExtensionStack extensionStack = new ExtensionStack(wsClient.getExtensionRegistry());
|
||||
ExtensionStack extensionStack = new ExtensionStack(wsClient.getExtensionRegistry(), Behavior.CLIENT);
|
||||
extensionStack.negotiate(wsClient.getObjectFactory(), httpClient.getByteBufferPool(), offeredExtensions, negotiatedExtensions);
|
||||
|
||||
// Get the negotiated subprotocol
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.eclipse.jetty.util.annotation.ManagedObject;
|
|||
import org.eclipse.jetty.util.component.Dumpable;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.core.Behavior;
|
||||
import org.eclipse.jetty.websocket.core.Extension;
|
||||
import org.eclipse.jetty.websocket.core.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.core.Frame;
|
||||
|
@ -51,13 +52,15 @@ public class ExtensionStack implements IncomingFrames, OutgoingFrames, Dumpable
|
|||
private static final Logger LOG = Log.getLogger(ExtensionStack.class);
|
||||
|
||||
private final WebSocketExtensionRegistry factory;
|
||||
private final Behavior behavior;
|
||||
private List<Extension> extensions;
|
||||
private IncomingFrames incoming;
|
||||
private OutgoingFrames outgoing;
|
||||
|
||||
public ExtensionStack(WebSocketExtensionRegistry factory)
|
||||
public ExtensionStack(WebSocketExtensionRegistry factory, Behavior behavior)
|
||||
{
|
||||
this.factory = factory;
|
||||
this.behavior = behavior;
|
||||
}
|
||||
|
||||
@ManagedAttribute(name = "Extension List", readonly = true)
|
||||
|
@ -131,13 +134,36 @@ public class ExtensionStack implements IncomingFrames, OutgoingFrames, Dumpable
|
|||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
for (ExtensionConfig offered : offeredConfigs)
|
||||
{
|
||||
if (offered.getParameterizedName().equals(config.getParameterizedName()))
|
||||
throw new BadMessageException("offered extension had bad parameters: ", t);
|
||||
}
|
||||
/* If there was an error creating the extension we need to differentiate between a
|
||||
bad ExtensionConfig offered by the client and a bad ExtensionConfig negotiated by the server.
|
||||
|
||||
throw new WebSocketException("negotiated extension had bad parameters: ", t);
|
||||
When deciding whether to throw a BadMessageException and send a 400 response or a WebSocketException
|
||||
and send a 500 response it depends on whether this is running on the client or the server. */
|
||||
switch (behavior)
|
||||
{
|
||||
case SERVER:
|
||||
{
|
||||
String parameterizedName = config.getParameterizedName();
|
||||
for (ExtensionConfig offered : offeredConfigs)
|
||||
{
|
||||
if (offered.getParameterizedName().equals(parameterizedName))
|
||||
throw new BadMessageException("could not instantiate offered extension", t);
|
||||
}
|
||||
throw new WebSocketException("could not instantiate negotiated extension", t);
|
||||
}
|
||||
case CLIENT:
|
||||
{
|
||||
String parameterizedName = config.getParameterizedName();
|
||||
for (ExtensionConfig offered : offeredConfigs)
|
||||
{
|
||||
if (offered.getParameterizedName().equals(parameterizedName))
|
||||
throw new WebSocketException("could not instantiate offered extension", t);
|
||||
}
|
||||
throw new BadMessageException("could not instantiate negotiated extension", t);
|
||||
}
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
if (ext == null)
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.eclipse.jetty.http.QuotedCSV;
|
|||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.util.DecoratedObjectFactory;
|
||||
import org.eclipse.jetty.websocket.core.Behavior;
|
||||
import org.eclipse.jetty.websocket.core.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.core.WebSocketExtensionRegistry;
|
||||
import org.eclipse.jetty.websocket.core.internal.ExtensionStack;
|
||||
|
@ -227,7 +228,7 @@ public class Negotiation
|
|||
if (extensionStack == null)
|
||||
{
|
||||
// Extension stack can decide to drop any of these extensions or their parameters
|
||||
extensionStack = new ExtensionStack(registry);
|
||||
extensionStack = new ExtensionStack(registry, Behavior.SERVER);
|
||||
extensionStack.negotiate(objectFactory, bufferPool, offeredExtensions, negotiatedExtensions);
|
||||
negotiatedExtensions = extensionStack.getNegotiatedExtensions();
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ public class GeneratorFrameFlagsTest
|
|||
|
||||
public void setup(Frame invalidFrame)
|
||||
{
|
||||
ExtensionStack exStack = new ExtensionStack(new WebSocketExtensionRegistry());
|
||||
ExtensionStack exStack = new ExtensionStack(new WebSocketExtensionRegistry(), Behavior.SERVER);
|
||||
exStack.negotiate(new DecoratedObjectFactory(), bufferPool, new LinkedList<>(), new LinkedList<>());
|
||||
this.channel = new WebSocketChannel(new AbstractTestFrameHandler(), Behavior.CLIENT, Negotiated.from(exStack));
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ public class GeneratorTest
|
|||
private static WebSocketChannel newChannel(Behavior behavior)
|
||||
{
|
||||
ByteBufferPool bufferPool = new MappedByteBufferPool();
|
||||
ExtensionStack exStack = new ExtensionStack(new WebSocketExtensionRegistry());
|
||||
ExtensionStack exStack = new ExtensionStack(new WebSocketExtensionRegistry(), Behavior.SERVER);
|
||||
exStack.negotiate(new DecoratedObjectFactory(), bufferPool, new LinkedList<>(), new LinkedList<>());
|
||||
return new WebSocketChannel(new AbstractTestFrameHandler(), behavior, Negotiated.from(exStack));
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ public class ParserCapture
|
|||
this.copy = copy;
|
||||
|
||||
ByteBufferPool bufferPool = new MappedByteBufferPool();
|
||||
ExtensionStack exStack = new ExtensionStack(new WebSocketExtensionRegistry());
|
||||
ExtensionStack exStack = new ExtensionStack(new WebSocketExtensionRegistry(), Behavior.SERVER);
|
||||
exStack.negotiate(new DecoratedObjectFactory(), bufferPool, new LinkedList<>(), new LinkedList<>());
|
||||
this.channel = new WebSocketChannel(new AbstractTestFrameHandler(), behavior, Negotiated.from(exStack));
|
||||
}
|
||||
|
|
|
@ -419,7 +419,7 @@ public class DeflateFrameExtensionTest extends AbstractExtensionTest
|
|||
private WebSocketChannel channelWithMaxMessageSize(int maxMessageSize)
|
||||
{
|
||||
ByteBufferPool bufferPool = new MappedByteBufferPool();
|
||||
ExtensionStack exStack = new ExtensionStack(new WebSocketExtensionRegistry());
|
||||
ExtensionStack exStack = new ExtensionStack(new WebSocketExtensionRegistry(), Behavior.SERVER);
|
||||
exStack.negotiate(new DecoratedObjectFactory(), bufferPool, new LinkedList<>(), new LinkedList<>());
|
||||
|
||||
WebSocketChannel channel = new WebSocketChannel(new AbstractTestFrameHandler(), Behavior.SERVER, Negotiated.from(exStack));
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.eclipse.jetty.io.MappedByteBufferPool;
|
|||
import org.eclipse.jetty.util.DecoratedObjectFactory;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.core.Behavior;
|
||||
import org.eclipse.jetty.websocket.core.Extension;
|
||||
import org.eclipse.jetty.websocket.core.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.core.IncomingFrames;
|
||||
|
@ -55,7 +56,7 @@ public class ExtensionStackTest
|
|||
{
|
||||
objectFactory = new DecoratedObjectFactory();
|
||||
bufferPool = new MappedByteBufferPool();
|
||||
stack = new ExtensionStack(new WebSocketExtensionRegistry());
|
||||
stack = new ExtensionStack(new WebSocketExtensionRegistry(), Behavior.SERVER);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
|
@ -153,7 +153,7 @@ public class ExtensionTool
|
|||
private WebSocketChannel newWebsocketChannel()
|
||||
{
|
||||
ByteBufferPool bufferPool = new MappedByteBufferPool();
|
||||
ExtensionStack exStack = new ExtensionStack(new WebSocketExtensionRegistry());
|
||||
ExtensionStack exStack = new ExtensionStack(new WebSocketExtensionRegistry(), Behavior.SERVER);
|
||||
exStack.negotiate(new DecoratedObjectFactory(), bufferPool, new LinkedList<>(), new LinkedList<>());
|
||||
WebSocketChannel channel = new WebSocketChannel(new AbstractTestFrameHandler(), Behavior.SERVER, Negotiated.from(exStack));
|
||||
return channel;
|
||||
|
|
Loading…
Reference in New Issue