1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.handler.codec.http.websocketx;
17
18 import io.netty5.buffer.api.BufferAllocator;
19 import io.netty5.handler.codec.http.DefaultFullHttpResponse;
20 import io.netty5.handler.codec.http.FullHttpRequest;
21 import io.netty5.handler.codec.http.FullHttpResponse;
22 import io.netty5.handler.codec.http.HttpHeaderNames;
23 import io.netty5.handler.codec.http.HttpHeaderValues;
24 import io.netty5.handler.codec.http.HttpHeaders;
25 import io.netty5.handler.codec.http.HttpResponseStatus;
26
27 import static io.netty5.handler.codec.http.HttpVersion.HTTP_1_1;
28
29
30
31
32
33
34
35 public class WebSocketServerHandshaker13 extends WebSocketServerHandshaker {
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 public WebSocketServerHandshaker13(
52 String webSocketURL, String subprotocols, boolean allowExtensions, int maxFramePayloadLength) {
53 this(webSocketURL, subprotocols, allowExtensions, maxFramePayloadLength, false);
54 }
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 public WebSocketServerHandshaker13(
74 String webSocketURL, String subprotocols, boolean allowExtensions, int maxFramePayloadLength,
75 boolean allowMaskMismatch) {
76 this(webSocketURL, subprotocols, WebSocketDecoderConfig.newBuilder()
77 .allowExtensions(allowExtensions)
78 .maxFramePayloadLength(maxFramePayloadLength)
79 .allowMaskMismatch(allowMaskMismatch)
80 .build());
81 }
82
83
84
85
86
87
88
89
90
91
92
93
94 public WebSocketServerHandshaker13(
95 String webSocketURL, String subprotocols, WebSocketDecoderConfig decoderConfig) {
96 super(WebSocketVersion.V13, webSocketURL, subprotocols, decoderConfig);
97 }
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133 @Override
134 protected FullHttpResponse newHandshakeResponse(BufferAllocator allocator, FullHttpRequest req,
135 HttpHeaders headers) {
136 HttpHeaders reqHeaders = req.headers();
137 if (!reqHeaders.contains(HttpHeaderNames.CONNECTION) ||
138 !reqHeaders.containsValue(HttpHeaderNames.CONNECTION, HttpHeaderValues.UPGRADE, true)) {
139 throw new WebSocketServerHandshakeException(
140 "not a WebSocket request: a |Connection| header must includes a token 'Upgrade'", req);
141 }
142
143 if (!reqHeaders.contains(HttpHeaderNames.UPGRADE, HttpHeaderValues.WEBSOCKET, true)) {
144 throw new WebSocketServerHandshakeException(
145 "not a WebSocket request: a |Upgrade| header must containing the value 'websocket'", req);
146 }
147
148 String key = reqHeaders.get(HttpHeaderNames.SEC_WEBSOCKET_KEY);
149 if (key == null) {
150 throw new WebSocketServerHandshakeException("not a WebSocket request: missing key", req);
151 }
152
153 FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.SWITCHING_PROTOCOLS,
154 allocator.allocate(0));
155 if (headers != null) {
156 res.headers().add(headers);
157 }
158
159 String accept = WebSocketUtil.calculateV13Accept(key);
160 res.headers().set(HttpHeaderNames.UPGRADE, HttpHeaderValues.WEBSOCKET)
161 .set(HttpHeaderNames.CONNECTION, HttpHeaderValues.UPGRADE)
162 .set(HttpHeaderNames.SEC_WEBSOCKET_ACCEPT, accept);
163
164 String subprotocols = reqHeaders.get(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL);
165 if (subprotocols != null) {
166 String selectedSubprotocol = selectSubprotocol(subprotocols);
167 if (selectedSubprotocol == null) {
168 if (logger.isDebugEnabled()) {
169 logger.debug("Requested subprotocol(s) not supported: {}", subprotocols);
170 }
171 } else {
172 res.headers().set(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL, selectedSubprotocol);
173 }
174 }
175 return res;
176 }
177
178 @Override
179 protected WebSocketFrameDecoder newWebsocketDecoder() {
180 return new WebSocket13FrameDecoder(decoderConfig());
181 }
182
183 @Override
184 protected WebSocketFrameEncoder newWebSocketEncoder() {
185 return new WebSocket13FrameEncoder(false);
186 }
187 }