1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.web.socket.sockjs.transport.handler;
18
19 import java.io.IOException;
20 import java.io.UnsupportedEncodingException;
21
22 import org.springframework.http.MediaType;
23 import org.springframework.http.server.ServerHttpRequest;
24 import org.springframework.http.server.ServerHttpResponse;
25 import org.springframework.util.MultiValueMap;
26 import org.springframework.util.StringUtils;
27 import org.springframework.web.socket.WebSocketHandler;
28 import org.springframework.web.socket.sockjs.SockJsException;
29 import org.springframework.web.socket.sockjs.frame.SockJsFrame;
30 import org.springframework.web.socket.sockjs.frame.SockJsFrameFormat;
31 import org.springframework.web.socket.sockjs.transport.SockJsSession;
32 import org.springframework.web.socket.sockjs.transport.SockJsSessionFactory;
33 import org.springframework.web.socket.sockjs.transport.session.AbstractHttpSockJsSession;
34 import org.springframework.web.util.UriComponentsBuilder;
35 import org.springframework.web.util.UriUtils;
36
37
38
39
40
41
42
43 public abstract class AbstractHttpSendingTransportHandler extends AbstractTransportHandler
44 implements SockJsSessionFactory {
45
46 @Override
47 public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
48 WebSocketHandler wsHandler, SockJsSession wsSession) throws SockJsException {
49
50 AbstractHttpSockJsSession sockJsSession = (AbstractHttpSockJsSession) wsSession;
51
52 String protocol = null;
53 sockJsSession.setAcceptedProtocol(protocol);
54
55
56 response.getHeaders().setContentType(getContentType());
57
58 handleRequestInternal(request, response, sockJsSession);
59 }
60
61 protected void handleRequestInternal(ServerHttpRequest request, ServerHttpResponse response,
62 AbstractHttpSockJsSession sockJsSession) throws SockJsException {
63
64 if (sockJsSession.isNew()) {
65 if (logger.isDebugEnabled()) {
66 logger.debug(request.getMethod() + " " + request.getURI());
67 }
68 sockJsSession.handleInitialRequest(request, response, getFrameFormat(request));
69 }
70 else if (sockJsSession.isClosed()) {
71 if (logger.isDebugEnabled()) {
72 logger.debug("Connection already closed (but not removed yet) for " + sockJsSession);
73 }
74 SockJsFrame frame = SockJsFrame.closeFrameGoAway();
75 try {
76 response.getBody().write(frame.getContentBytes());
77 }
78 catch (IOException ex) {
79 throw new SockJsException("Failed to send " + frame, sockJsSession.getId(), ex);
80 }
81 }
82 else if (!sockJsSession.isActive()) {
83 if (logger.isTraceEnabled()) {
84 logger.trace("Starting " + getTransportType() + " async request.");
85 }
86 sockJsSession.handleSuccessiveRequest(request, response, getFrameFormat(request));
87 }
88 else {
89 if (logger.isDebugEnabled()) {
90 logger.debug("Another " + getTransportType() + " connection still open for " + sockJsSession);
91 }
92 String formattedFrame = getFrameFormat(request).format(SockJsFrame.closeFrameAnotherConnectionOpen());
93 try {
94 response.getBody().write(formattedFrame.getBytes(SockJsFrame.CHARSET));
95 }
96 catch (IOException ex) {
97 throw new SockJsException("Failed to send " + formattedFrame, sockJsSession.getId(), ex);
98 }
99 }
100 }
101
102
103 protected abstract MediaType getContentType();
104
105 protected abstract SockJsFrameFormat getFrameFormat(ServerHttpRequest request);
106
107
108 protected final String getCallbackParam(ServerHttpRequest request) {
109 String query = request.getURI().getQuery();
110 MultiValueMap<String, String> params = UriComponentsBuilder.newInstance().query(query).build().getQueryParams();
111 String value = params.getFirst("c");
112 try {
113 return (!StringUtils.isEmpty(value) ? UriUtils.decode(value, "UTF-8") : null);
114 }
115 catch (UnsupportedEncodingException ex) {
116
117 throw new SockJsException("Unable to decode callback query parameter", null, ex);
118 }
119 }
120
121 }