444617 - Expose local and remote socket address to applications

+ Exposing 2 new automatically added userProperties
  * "javax.websocket.endpoint.localAddress" 
  * "javax.websocket.endpoint.remoteAddress"
  these are both java.net.InetSocketAddress objects
This commit is contained in:
Joakim Erdfelt 2014-09-22 12:43:37 -07:00
parent 1ce66f38a0
commit d6082b2d65
3 changed files with 104 additions and 0 deletions

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.websocket.jsr356.server;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.websocket.Extension;
import javax.websocket.Extension.Parameter;
import javax.websocket.server.ServerEndpointConfig;
@ -40,6 +41,8 @@ import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
public class JsrCreator implements WebSocketCreator
{
public static final String PROP_REMOTE_ADDRESS = "javax.websocket.endpoint.remoteAddress";
public static final String PROP_LOCAL_ADDRESS = "javax.websocket.endpoint.localAddress";
private static final Logger LOG = Log.getLogger(JsrCreator.class);
private final ServerEndpointMetadata metadata;
private final ExtensionFactory extensionFactory;
@ -62,6 +65,13 @@ public class JsrCreator implements WebSocketCreator
// Establish a copy of the config, so that the UserProperties are unique
// per upgrade request.
config = new BasicServerEndpointConfig(config);
// Bug 444617 - Expose localAddress and remoteAddress for jsr modify handshake to use
// This is being implemented as an optional set of userProperties so that
// it is not JSR api breaking. A few users on #jetty and a few from cometd
// have asked for access to this information.
config.getUserProperties().put(PROP_LOCAL_ADDRESS,req.getLocalSocketAddress());
config.getUserProperties().put(PROP_REMOTE_ADDRESS,req.getRemoteSocketAddress());
// Get Configurator from config object (not guaranteed to be unique per endpoint upgrade)
ServerEndpointConfig.Configurator configurator = config.getConfigurator();

View File

@ -20,6 +20,9 @@ package org.eclipse.jetty.websocket.jsr356.server;
import static org.hamcrest.Matchers.*;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.InetSocketAddress;
import java.net.URI;
import java.util.Collections;
import java.util.List;
@ -204,7 +207,46 @@ public class ConfiguratorTest
return response.toString();
}
}
public static class AddrConfigurator extends ServerEndpointConfig.Configurator
{
@Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response)
{
InetSocketAddress local = (InetSocketAddress)sec.getUserProperties().get(JsrCreator.PROP_LOCAL_ADDRESS);
InetSocketAddress remote = (InetSocketAddress)sec.getUserProperties().get(JsrCreator.PROP_REMOTE_ADDRESS);
sec.getUserProperties().put("found.local", local);
sec.getUserProperties().put("found.remote", remote);
super.modifyHandshake(sec,request,response);
}
}
@ServerEndpoint(value = "/addr", configurator = AddrConfigurator.class)
public static class AddressSocket
{
@OnMessage
public String onMessage(Session session, String msg)
{
StringBuilder response = new StringBuilder();
appendPropValue(session,response,"javax.websocket.endpoint.localAddress");
appendPropValue(session,response,"javax.websocket.endpoint.remoteAddress");
appendPropValue(session,response,"found.local");
appendPropValue(session,response,"found.remote");
return response.toString();
}
private void appendPropValue(Session session, StringBuilder response, String key)
{
InetSocketAddress value = (InetSocketAddress)session.getUserProperties().get(key);
response.append("[").append(key).append("] = ");
response.append(toSafeAddr(value));
response.append(System.lineSeparator());
}
}
private static Server server;
private static URI baseServerUri;
@ -226,6 +268,7 @@ public class ConfiguratorTest
container.addEndpoint(NoExtensionsSocket.class);
container.addEndpoint(ProtocolsSocket.class);
container.addEndpoint(UniqueUserPropsSocket.class);
container.addEndpoint(AddressSocket.class);
server.start();
String host = connector.getHost();
@ -239,6 +282,15 @@ public class ConfiguratorTest
LOG.debug("Server started on {}",baseServerUri);
}
public static String toSafeAddr(InetSocketAddress addr)
{
if (addr == null)
{
return "<null>";
}
return String.format("%s:%d",addr.getAddress().getHostAddress(),addr.getPort());
}
@AfterClass
public static void stopServer() throws Exception
{
@ -331,6 +383,37 @@ public class ConfiguratorTest
}
}
@Test
public void testUserPropsAddress() throws Exception
{
URI uri = baseServerUri.resolve("/addr");
// First request
try (BlockheadClient client = new BlockheadClient(uri))
{
client.connect();
client.sendStandardRequest();
client.expectUpgradeResponse();
InetSocketAddress expectedLocal = client.getLocalSocketAddress();
InetSocketAddress expectedRemote = client.getRemoteSocketAddress();
client.write(new TextFrame().setPayload("addr"));
EventQueue<WebSocketFrame> frames = client.readFrames(1,1,TimeUnit.SECONDS);
WebSocketFrame frame = frames.poll();
StringWriter expected = new StringWriter();
PrintWriter out = new PrintWriter(expected);
// local <-> remote are opposite on server (duh)
out.printf("[javax.websocket.endpoint.localAddress] = %s%n", toSafeAddr(expectedRemote));
out.printf("[javax.websocket.endpoint.remoteAddress] = %s%n", toSafeAddr(expectedLocal));
out.printf("[found.local] = %s%n",toSafeAddr(expectedRemote));
out.printf("[found.remote] = %s%n",toSafeAddr(expectedLocal));
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is(expected.toString()));
}
}
/**
* Test of Sec-WebSocket-Protocol, as seen in RFC-6455, 1 protocol
*/

View File

@ -450,6 +450,11 @@ public class BlockheadClient implements OutgoingFrames, ConnectionStateListener,
return destHttpURI;
}
public InetSocketAddress getLocalSocketAddress()
{
return (InetSocketAddress)socket.getLocalSocketAddress();
}
public IOState getIOState()
{
return ioState;
@ -459,6 +464,12 @@ public class BlockheadClient implements OutgoingFrames, ConnectionStateListener,
{
return protocols;
}
public InetSocketAddress getRemoteSocketAddress()
{
return (InetSocketAddress)socket.getRemoteSocketAddress();
}
public String getRequestHost()
{