Skip to content

Commit 01feae0

Browse files
committed
Polish WebSocketSession
Update methods available on WebSocketSession interface. Introduce DelegatingWebSocketSession interface.
1 parent 14ac023 commit 01feae0

File tree

36 files changed

+733
-588
lines changed

36 files changed

+733
-588
lines changed

spring-messaging/src/main/java/org/springframework/messaging/handler/websocket/SubProtocolWebSocketHandler.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.springframework.messaging.MessagingException;
3131
import org.springframework.util.Assert;
3232
import org.springframework.util.CollectionUtils;
33+
import org.springframework.util.StringUtils;
3334
import org.springframework.web.socket.CloseStatus;
3435
import org.springframework.web.socket.WebSocketHandler;
3536
import org.springframework.web.socket.WebSocketMessage;
@@ -133,7 +134,7 @@ public void afterConnectionEstablished(WebSocketSession session) throws Exceptio
133134
protected final SubProtocolHandler getProtocolHandler(WebSocketSession session) {
134135
SubProtocolHandler handler;
135136
String protocol = session.getAcceptedProtocol();
136-
if (protocol != null) {
137+
if (!StringUtils.isEmpty(protocol)) {
137138
handler = this.protocolHandlers.get(protocol);
138139
Assert.state(handler != null,
139140
"No handler for sub-protocol '" + protocol + "', handlers=" + this.protocolHandlers);

spring-messaging/src/test/java/org/springframework/messaging/handler/websocket/SubProtocolWebSocketHandlerTests.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,18 @@ public void subProtocolNoMatch() throws Exception {
9191
}
9292

9393
@Test
94-
public void noSubProtocol() throws Exception {
94+
public void nullSubProtocol() throws Exception {
95+
this.webSocketHandler.setDefaultProtocolHandler(defaultHandler);
96+
this.webSocketHandler.afterConnectionEstablished(session);
97+
98+
verify(this.defaultHandler).afterSessionStarted(session, this.channel);
99+
verify(this.stompHandler, times(0)).afterSessionStarted(session, this.channel);
100+
verify(this.mqttHandler, times(0)).afterSessionStarted(session, this.channel);
101+
}
102+
103+
@Test
104+
public void emptySubProtocol() throws Exception {
105+
this.session.setAcceptedProtocol("");
95106
this.webSocketHandler.setDefaultProtocolHandler(defaultHandler);
96107
this.webSocketHandler.afterConnectionEstablished(session);
97108

spring-web/src/main/java/org/springframework/http/server/ServerHttpRequest.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.http.server;
1818

19+
import java.net.InetSocketAddress;
1920
import java.security.Principal;
2021
import java.util.Map;
2122

@@ -51,14 +52,14 @@ public interface ServerHttpRequest extends HttpRequest, HttpInputMessage {
5152
Principal getPrincipal();
5253

5354
/**
54-
* Return the host name of the endpoint on the other end.
55+
* Return the address on which the request was received.
5556
*/
56-
String getRemoteHostName();
57+
InetSocketAddress getLocalAddress();
5758

5859
/**
59-
* Return the IP address of the endpoint on the other end.
60+
* Return the address of the remote client.
6061
*/
61-
String getRemoteAddress();
62+
InetSocketAddress getRemoteAddress();
6263

6364
/**
6465
* Return a control that allows putting the request in asynchronous mode so the

spring-web/src/main/java/org/springframework/http/server/ServletServerHttpRequest.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.io.InputStream;
2323
import java.io.OutputStreamWriter;
2424
import java.io.Writer;
25+
import java.net.InetSocketAddress;
2526
import java.net.URI;
2627
import java.net.URISyntaxException;
2728
import java.net.URLEncoder;
@@ -147,13 +148,13 @@ public Principal getPrincipal() {
147148
}
148149

149150
@Override
150-
public String getRemoteHostName() {
151-
return this.servletRequest.getRemoteHost();
151+
public InetSocketAddress getLocalAddress() {
152+
return new InetSocketAddress(this.servletRequest.getLocalName(), this.servletRequest.getLocalPort());
152153
}
153154

154155
@Override
155-
public String getRemoteAddress() {
156-
return this.servletRequest.getRemoteAddr();
156+
public InetSocketAddress getRemoteAddress() {
157+
return new InetSocketAddress(this.servletRequest.getRemoteHost(), this.servletRequest.getRemotePort());
157158
}
158159

159160
@Override

spring-websocket/src/main/java/org/springframework/web/socket/WebSocketSession.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@
1717
package org.springframework.web.socket;
1818

1919
import java.io.IOException;
20+
import java.net.InetSocketAddress;
2021
import java.net.URI;
2122
import java.security.Principal;
2223

24+
import org.springframework.http.HttpHeaders;
25+
2326
/**
2427
* A WebSocket session abstraction. Allows sending messages over a WebSocket connection
2528
* and closing it.
@@ -29,6 +32,7 @@
2932
*/
3033
public interface WebSocketSession {
3134

35+
3236
/**
3337
* Return a unique session identifier.
3438
*/
@@ -40,9 +44,9 @@ public interface WebSocketSession {
4044
URI getUri();
4145

4246
/**
43-
* Return whether the underlying socket is using a secure transport.
47+
* Return the headers used in the handshake request.
4448
*/
45-
boolean isSecure();
49+
HttpHeaders getHandshakeHeaders();
4650

4751
/**
4852
* Return a {@link java.security.Principal} instance containing the name of the
@@ -52,17 +56,18 @@ public interface WebSocketSession {
5256
Principal getPrincipal();
5357

5458
/**
55-
* Return the host name of the endpoint on the other end.
59+
* Return the address on which the request was received.
5660
*/
57-
String getRemoteHostName();
61+
InetSocketAddress getLocalAddress();
5862

5963
/**
60-
* Return the IP address of the endpoint on the other end.
64+
* Return the address of the remote client.
6165
*/
62-
String getRemoteAddress();
66+
InetSocketAddress getRemoteAddress();
6367

6468
/**
65-
* Return the negotiated sub-protocol or {@code null} if none was specified.
69+
* Return the negotiated sub-protocol or {@code null} if none was specified or
70+
* negotiated successfully.
6671
*/
6772
String getAcceptedProtocol();
6873

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,41 @@
3232
* @author Rossen Stoyanchev
3333
* @since 4.0
3434
*/
35-
public abstract class AbstractWebSocketSesssionAdapter<T> implements ConfigurableWebSocketSession {
35+
public abstract class AbstractWebSocketSesssion<T> implements DelegatingWebSocketSession<T> {
3636

3737
protected final Log logger = LogFactory.getLog(getClass());
3838

39+
private T delegateSession;
3940

40-
public abstract void initSession(T session);
41+
42+
/**
43+
* @return the WebSocket session to delegate to
44+
*/
45+
public T getDelegateSession() {
46+
return this.delegateSession;
47+
}
48+
49+
50+
@Override
51+
public void afterSessionInitialized(T session) {
52+
Assert.notNull(session, "session must not be null");
53+
this.delegateSession = session;
54+
}
55+
56+
protected final void checkDelegateSessionInitialized() {
57+
Assert.state(this.delegateSession != null, "WebSocket session is not yet initialized");
58+
}
4159

4260
@Override
4361
public final void sendMessage(WebSocketMessage message) throws IOException {
62+
63+
checkDelegateSessionInitialized();
64+
Assert.isTrue(isOpen(), "Cannot send message after connection closed.");
65+
4466
if (logger.isTraceEnabled()) {
4567
logger.trace("Sending " + message + ", " + this);
4668
}
47-
Assert.isTrue(isOpen(), "Cannot send message after connection closed.");
69+
4870
if (message instanceof TextMessage) {
4971
sendTextMessage((TextMessage) message);
5072
}
@@ -60,13 +82,15 @@ else if (message instanceof BinaryMessage) {
6082

6183
protected abstract void sendBinaryMessage(BinaryMessage message) throws IOException ;
6284

85+
6386
@Override
64-
public void close() throws IOException {
87+
public final void close() throws IOException {
6588
close(CloseStatus.NORMAL);
6689
}
6790

6891
@Override
6992
public final void close(CloseStatus status) throws IOException {
93+
checkDelegateSessionInitialized();
7094
if (logger.isDebugEnabled()) {
7195
logger.debug("Closing " + this);
7296
}
@@ -75,6 +99,7 @@ public final void close(CloseStatus status) throws IOException {
7599

76100
protected abstract void closeInternal(CloseStatus status) throws IOException;
77101

102+
78103
@Override
79104
public String toString() {
80105
return "WebSocket session id=" + getId();
Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,34 +16,25 @@
1616

1717
package org.springframework.web.socket.adapter;
1818

19-
import java.net.URI;
20-
import java.security.Principal;
21-
2219
import org.springframework.web.socket.WebSocketSession;
23-
import org.springframework.web.socket.server.DefaultHandshakeHandler;
20+
2421

2522
/**
26-
* A WebSocketSession with configurable properties.
23+
* A contract for {@link WebSocketSession} implementations that delegate to another
24+
* WebSocket session (e.g. a native session).
25+
*
26+
* @param T the type of the delegate WebSocket session
2727
*
2828
* @author Rossen Stoyanchev
2929
* @since 4.0
3030
*/
31-
public interface ConfigurableWebSocketSession extends WebSocketSession {
32-
33-
void setUri(URI uri);
31+
public interface DelegatingWebSocketSession<T> extends WebSocketSession {
3432

35-
void setRemoteHostName(String name);
36-
37-
void setRemoteAddress(String address);
38-
39-
void setPrincipal(Principal principal);
4033

4134
/**
42-
* Set the protocol accepted as part of the WebSocket handshake. This property can be
43-
* used when the WebSocket handshake is performed through
44-
* {@link DefaultHandshakeHandler} rather than the underlying WebSocket runtime, or
45-
* when there is no WebSocket handshake (e.g. SockJS HTTP fallback options)
35+
* Invoked when the delegate WebSocket session has been initialized.
4636
*/
47-
void setAcceptedProtocol(String protocol);
37+
void afterSessionInitialized(T session);
38+
4839

4940
}
Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,22 @@
2828
import org.springframework.web.socket.support.ExceptionWebSocketHandlerDecorator;
2929

3030
/**
31-
* Adapts {@link WebSocketHandler} to the Jetty 9 {@link WebSocketListener}.
31+
* Adapts {@link WebSocketHandler} to the Jetty 9 WebSocket API.
3232
*
3333
* @author Phillip Webb
34+
* @author Rossen Stoyanchev
3435
* @since 4.0
3536
*/
36-
public class JettyWebSocketListenerAdapter implements WebSocketListener {
37+
public class JettyWebSocketHandlerAdapter implements WebSocketListener {
3738

38-
private static final Log logger = LogFactory.getLog(JettyWebSocketListenerAdapter.class);
39+
private static final Log logger = LogFactory.getLog(JettyWebSocketHandlerAdapter.class);
3940

4041
private final WebSocketHandler webSocketHandler;
4142

42-
private final JettyWebSocketSessionAdapter wsSession;
43+
private final JettyWebSocketSession wsSession;
4344

4445

45-
public JettyWebSocketListenerAdapter(WebSocketHandler webSocketHandler, JettyWebSocketSessionAdapter wsSession) {
46+
public JettyWebSocketHandlerAdapter(WebSocketHandler webSocketHandler, JettyWebSocketSession wsSession) {
4647
Assert.notNull(webSocketHandler, "webSocketHandler must not be null");
4748
Assert.notNull(wsSession, "wsSession must not be null");
4849
this.webSocketHandler = webSocketHandler;
@@ -52,8 +53,8 @@ public JettyWebSocketListenerAdapter(WebSocketHandler webSocketHandler, JettyWeb
5253

5354
@Override
5455
public void onWebSocketConnect(Session session) {
55-
this.wsSession.initSession(session);
5656
try {
57+
this.wsSession.afterSessionInitialized(session);
5758
this.webSocketHandler.afterConnectionEstablished(this.wsSession);
5859
}
5960
catch (Throwable t) {

0 commit comments

Comments
 (0)