From c63dbe45e01eebdd7533585a458943ded12d6a72 Mon Sep 17 00:00:00 2001 From: Greg Thomas Date: Tue, 8 Jul 2014 16:58:01 +0100 Subject: [PATCH] Add support for path in websocket URL --- .../stomp/client/ClientContextImpl.java | 26 ++++++---- .../stilts/stomp/client/StompClient.java | 21 ++++++-- .../client/StompClientPipelineFactory.java | 8 ++-- .../stomp/client/protocol/ClientContext.java | 17 ++++--- .../WebSocketConnectionNegotiator.java | 27 +++++------ .../stomp/client/MockClientContext.java | 48 ++++++++++++------- .../WebSocketConnectionNegotiatorTest.java | 6 +-- .../src/test/resources/logging.properties | 2 +- 8 files changed, 93 insertions(+), 62 deletions(-) diff --git a/stomp-client/src/main/java/org/projectodd/stilts/stomp/client/ClientContextImpl.java b/stomp-client/src/main/java/org/projectodd/stilts/stomp/client/ClientContextImpl.java index 7c91b362..2b48bf81 100644 --- a/stomp-client/src/main/java/org/projectodd/stilts/stomp/client/ClientContextImpl.java +++ b/stomp-client/src/main/java/org/projectodd/stilts/stomp/client/ClientContextImpl.java @@ -1,12 +1,12 @@ /* * Copyright 2011 Red Hat, Inc, and individual contributors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,6 +17,7 @@ package org.projectodd.stilts.stomp.client; import java.net.InetSocketAddress; +import java.net.URI; import javax.net.ssl.SSLContext; @@ -26,26 +27,31 @@ import org.projectodd.stilts.stomp.protocol.StompFrame.Version; class ClientContextImpl implements ClientContext { - + ClientContextImpl(StompClient client) { this.client = client; } - + @Override public InetSocketAddress getServerAddress() { return this.client.getServerAddress(); } + @Override + public URI getWebSocketAddress() { + return client.getWebSocketAddress(); + } + @Override public State getConnectionState() { return this.client.getConnectionState(); } - + @Override public Version getVersion() { return this.client.getVersion(); } - + @Override public boolean isSecure() { return this.client.isSecure(); @@ -59,8 +65,8 @@ public void setConnectionState(State connectionState) { @Override public void setVersion(Version version) { this.client.setVersion( version ); - } - + } + @Override public void messageReceived(StompMessage message) { this.client.messageReceived( message ); @@ -75,7 +81,7 @@ public void errorReceived(StompMessage message) { public void receiptReceived(String receiptId) { this.client.receiptReceived( receiptId ); } - + @Override public SSLContext getSSLContext() { return this.client.getSSLContext(); diff --git a/stomp-client/src/main/java/org/projectodd/stilts/stomp/client/StompClient.java b/stomp-client/src/main/java/org/projectodd/stilts/stomp/client/StompClient.java index 4213971e..d1fa5b1e 100644 --- a/stomp-client/src/main/java/org/projectodd/stilts/stomp/client/StompClient.java +++ b/stomp-client/src/main/java/org/projectodd/stilts/stomp/client/StompClient.java @@ -1,12 +1,12 @@ /* * Copyright 2011 Red Hat, Inc, and individual contributors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -103,16 +103,21 @@ public StompClient(URI uri, SSLContext sslContext) throws URISyntaxException { this.useSSL = true; } } - + if ( port < 0 ) { if ( useSSL ) { port = Constants.DEFAULT_SECURE_PORT; } else { port = Constants.DEFAULT_PORT; } - + } this.serverAddress = new InetSocketAddress( host, port ); + if( useWebSockets ) { + this.webSocketAddress = new URI(this.useSSL ? "wss" : "ws" + "://" + host + ":" + port + uri.getPath()); + } else { + this.webSocketAddress = null; + } } public boolean isSecure() { @@ -459,7 +464,12 @@ protected ClientSocketChannelFactory createChannelFactory() { return new NioClientSocketChannelFactory( bossExecutor, workerExecutor, 2 ); } + public URI getWebSocketAddress() { + return webSocketAddress; + } + private static final Callable NOOP = new Callable() { + @Override public Void call() throws Exception { return null; } @@ -485,6 +495,7 @@ public Void call() throws Exception { private boolean destroyExecutor = false; private Channel channel; private InetSocketAddress serverAddress; + private final URI webSocketAddress; private Version version = Version.VERSION_1_0; private boolean useWebSockets = false; private boolean useSSL = false; diff --git a/stomp-client/src/main/java/org/projectodd/stilts/stomp/client/StompClientPipelineFactory.java b/stomp-client/src/main/java/org/projectodd/stilts/stomp/client/StompClientPipelineFactory.java index df989a1c..6555761a 100644 --- a/stomp-client/src/main/java/org/projectodd/stilts/stomp/client/StompClientPipelineFactory.java +++ b/stomp-client/src/main/java/org/projectodd/stilts/stomp/client/StompClientPipelineFactory.java @@ -1,12 +1,12 @@ /* * Copyright 2011 Red Hat, Inc, and individual contributors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -74,7 +74,7 @@ public ChannelPipeline getPipeline() throws Exception { if (this.handshake != null) { pipeline.addLast( "http-encoder", new HttpRequestEncoder() ); pipeline.addLast( "http-decoder", new WebSocketHttpResponseDecoder( this.handshake ) ); - pipeline.addLast( "websocket-connection-negotiator", new WebSocketConnectionNegotiator( this.clientContext.getServerAddress(), this.handshake, this.clientContext.isSecure() ) ); + pipeline.addLast( "websocket-connection-negotiator", new WebSocketConnectionNegotiator( this.clientContext.getWebSocketAddress(), this.handshake ) ); pipeline.addLast( "stomp-frame-decoder", new WebSocketStompFrameDecoder() ); pipeline.addLast( "stomp-frame-encoder", new WebSocketStompFrameEncoder() ); } else { diff --git a/stomp-client/src/main/java/org/projectodd/stilts/stomp/client/protocol/ClientContext.java b/stomp-client/src/main/java/org/projectodd/stilts/stomp/client/protocol/ClientContext.java index a6bcc286..8996d862 100644 --- a/stomp-client/src/main/java/org/projectodd/stilts/stomp/client/protocol/ClientContext.java +++ b/stomp-client/src/main/java/org/projectodd/stilts/stomp/client/protocol/ClientContext.java @@ -1,12 +1,12 @@ /* * Copyright 2011 Red Hat, Inc, and individual contributors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,6 +17,7 @@ package org.projectodd.stilts.stomp.client.protocol; import java.net.InetSocketAddress; +import java.net.URI; import javax.net.ssl.SSLContext; @@ -25,17 +26,19 @@ import org.projectodd.stilts.stomp.protocol.StompFrame.Version; public interface ClientContext { - + InetSocketAddress getServerAddress(); + URI getWebSocketAddress(); + State getConnectionState(); Version getVersion(); - + boolean isSecure(); SSLContext getSSLContext(); - + void setConnectionState(State state); void setVersion(Version version); - + void receiptReceived(String receiptId); void messageReceived(StompMessage message); void errorReceived(StompMessage message); diff --git a/stomp-client/src/main/java/org/projectodd/stilts/stomp/client/protocol/websockets/WebSocketConnectionNegotiator.java b/stomp-client/src/main/java/org/projectodd/stilts/stomp/client/protocol/websockets/WebSocketConnectionNegotiator.java index 27e2de23..d65902a1 100644 --- a/stomp-client/src/main/java/org/projectodd/stilts/stomp/client/protocol/websockets/WebSocketConnectionNegotiator.java +++ b/stomp-client/src/main/java/org/projectodd/stilts/stomp/client/protocol/websockets/WebSocketConnectionNegotiator.java @@ -1,6 +1,5 @@ package org.projectodd.stilts.stomp.client.protocol.websockets; -import java.net.InetSocketAddress; import java.net.URI; import java.security.NoSuchAlgorithmException; @@ -20,27 +19,26 @@ import org.projectodd.stilts.stomp.protocol.websocket.WebSocketDisconnectionNegotiator; /** WebSockets protocol connection negotiator. - * + * *

This handler reacts to Netty's CONNECTED event and handles the handshake * of the WebSockets HTTP upgrade handshake. Upon successful completion, it forwards * a CONNECTED event upstream to the underlying protocol making use of the websocket * transport. For instance, STOMP.

- * + * * @author Bob McWhirter */ public class WebSocketConnectionNegotiator extends SimpleChannelUpstreamHandler { - - public WebSocketConnectionNegotiator(InetSocketAddress serverAddress, Handshake handshake, boolean useSSL) throws NoSuchAlgorithmException { - this.serverAddress = serverAddress; + + public WebSocketConnectionNegotiator(URI webSocketAddress, Handshake handshake) throws NoSuchAlgorithmException { + this.webSocketAddress = webSocketAddress; this.handshake = handshake; - this.useSSL = useSSL; } @Override public void channelConnected(ChannelHandlerContext context, ChannelStateEvent e) throws Exception { - URI uri = new URI( ( this.useSSL ? "wss" : "ws" ) + "://" + this.serverAddress.getHostName() + ":" + this.serverAddress.getPort() + "/" ); - HttpRequest request = this.handshake.generateRequest( uri ); + + HttpRequest request = this.handshake.generateRequest( this.webSocketAddress ); this.connectedEvent = e; Channel channel = context.getChannel(); Channels.write( channel, request ); @@ -50,7 +48,7 @@ public void channelConnected(ChannelHandlerContext context, ChannelStateEvent e) public void messageReceived(ChannelHandlerContext context, MessageEvent e) throws Exception { if (e.getMessage() instanceof HttpResponse) { HttpResponse response = (HttpResponse) e.getMessage(); - + if ( this.handshake.isComplete( response) ) { ChannelPipeline pipeline = context.getPipeline(); if (pipeline.get( WebSocketHttpResponseDecoder.class ) != null) { @@ -63,15 +61,15 @@ public void messageReceived(ChannelHandlerContext context, MessageEvent e) throw } else { pipeline.addAfter( "websockets-decoder", "websockets-encoder", this.handshake.newEncoder() ); } - + ChannelHandler[] additionalHandlers = this.handshake.newAdditionalHandlers(); String currentTail = "websockets-decoder"; for ( ChannelHandler each : additionalHandlers ) { String handlerName = "additional-" + each.getClass().getSimpleName(); - pipeline.addAfter( currentTail, handlerName, each); + pipeline.addAfter( currentTail, handlerName, each); currentTail = handlerName; } - + context.sendUpstream( this.connectedEvent ); pipeline.replace( this, "websocket-disconnection-negotiator", new WebSocketDisconnectionNegotiator() ); } @@ -81,8 +79,7 @@ public void messageReceived(ChannelHandlerContext context, MessageEvent e) throw } private static final Logger log = Logger.getLogger( "stomp.proto.client.websocket" ); - private InetSocketAddress serverAddress; - private boolean useSSL; + private final URI webSocketAddress; private Handshake handshake; private ChannelStateEvent connectedEvent; diff --git a/stomp-client/src/test/java/org/projectodd/stilts/stomp/client/MockClientContext.java b/stomp-client/src/test/java/org/projectodd/stilts/stomp/client/MockClientContext.java index d6cf6336..ab91c199 100644 --- a/stomp-client/src/test/java/org/projectodd/stilts/stomp/client/MockClientContext.java +++ b/stomp-client/src/test/java/org/projectodd/stilts/stomp/client/MockClientContext.java @@ -1,6 +1,7 @@ package org.projectodd.stilts.stomp.client; import java.net.InetSocketAddress; +import java.net.URI; import java.util.ArrayList; import java.util.List; @@ -16,32 +17,44 @@ public class MockClientContext implements ClientContext { public void setServerAddress(InetSocketAddress serverAddress) { this.serverAddress = serverAddress; } - + + @Override public InetSocketAddress getServerAddress() { return this.serverAddress; } - - public void setSecure(boolean secure) { + + public void setWebSocketAddress(URI webSocketAddress) { + this.webSocketAddress = webSocketAddress; + } + + @Override + public URI getWebSocketAddress() { + return webSocketAddress; + } + + public void setSecure(boolean secure) { this.secure = secure; } - - public boolean isSecure() { + + @Override + public boolean isSecure() { return this.secure; } - + public void setSSLContext(SSLContext sslContext) { this.sslContext = sslContext; } - - public SSLContext getSSLContext() { + + @Override + public SSLContext getSSLContext() { return this.sslContext; } - + @Override public State getConnectionState() { return this.state; } - + @Override public Version getVersion() { return this.version; @@ -56,7 +69,7 @@ public void setConnectionState(State state) { public void receiptReceived(String receiptId) { this.receipts.add( receiptId ); } - + public List getReceipts() { return this.receipts; } @@ -65,7 +78,7 @@ public List getReceipts() { public void messageReceived(StompMessage message) { this.messages.add( message ); } - + public List getMessages() { return this.messages; } @@ -75,7 +88,7 @@ public void errorReceived(StompMessage message) { this.errors.add( message ); } - + public List getErrors() { return this.errors; } @@ -83,15 +96,16 @@ public List getErrors() { @Override public void setVersion(Version version) { this.version = version; - } - + } + + private URI webSocketAddress; private InetSocketAddress serverAddress; private State state; private Version version = Version.VERSION_1_0; private boolean secure = false; private SSLContext sslContext; - - + + private List receipts = new ArrayList(); private List messages = new ArrayList(); private List errors = new ArrayList(); diff --git a/stomp-client/src/test/java/org/projectodd/stilts/stomp/client/protocol/websockets/WebSocketConnectionNegotiatorTest.java b/stomp-client/src/test/java/org/projectodd/stilts/stomp/client/protocol/websockets/WebSocketConnectionNegotiatorTest.java index f8e310d0..0a084378 100644 --- a/stomp-client/src/test/java/org/projectodd/stilts/stomp/client/protocol/websockets/WebSocketConnectionNegotiatorTest.java +++ b/stomp-client/src/test/java/org/projectodd/stilts/stomp/client/protocol/websockets/WebSocketConnectionNegotiatorTest.java @@ -4,7 +4,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import java.net.InetSocketAddress; +import java.net.URI; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; @@ -28,7 +28,7 @@ public void testConnect() throws Exception { Ietf00Handshake handshake = new Ietf00Handshake(); HandlerEmbedder handler = new HandlerEmbedder( false, new WebSocketHttpResponseDecoder( handshake ), - new WebSocketConnectionNegotiator( new InetSocketAddress( "localhost", 8675 ), handshake, false ) ); + new WebSocketConnectionNegotiator( URI.create( "ws://localhost:8675/" ), handshake ) ); ChannelPipeline pipeline = handler.getPipeline(); @@ -68,7 +68,7 @@ public void testConnectFailure() throws Exception { Ietf00Handshake handshake = new Ietf00Handshake(); HandlerEmbedder handler = new HandlerEmbedder( false, new WebSocketHttpResponseDecoder( handshake ), - new WebSocketConnectionNegotiator( new InetSocketAddress( "localhost", 8675 ) , handshake, false ) ); + new WebSocketConnectionNegotiator( URI.create( "ws://localhost:8675/" ), handshake ) ); ChannelPipeline pipeline = handler.getPipeline(); diff --git a/stomp-client/src/test/resources/logging.properties b/stomp-client/src/test/resources/logging.properties index aaafdd54..9cb1df9b 100644 --- a/stomp-client/src/test/resources/logging.properties +++ b/stomp-client/src/test/resources/logging.properties @@ -33,7 +33,7 @@ logger.handlers=FILE, CONSOLE # Console handler configuration handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler handler.CONSOLE.properties=autoFlush -handler.CONSOLE.level=INFO +handler.CONSOLE.level=DEBUG handler.CONSOLE.autoFlush=true handler.CONSOLE.formatter=PATTERN