1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.websocket.client;
20
21 import java.net.CookieStore;
22 import java.net.HttpCookie;
23 import java.net.URI;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Random;
29 import java.util.Set;
30
31 import org.eclipse.jetty.util.B64Code;
32 import org.eclipse.jetty.util.MultiMap;
33 import org.eclipse.jetty.util.StringUtil;
34 import org.eclipse.jetty.util.UrlEncoded;
35 import org.eclipse.jetty.util.log.Log;
36 import org.eclipse.jetty.util.log.Logger;
37 import org.eclipse.jetty.websocket.api.UpgradeRequest;
38 import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
39
40
41
42
43 public class ClientUpgradeRequest extends UpgradeRequest
44 {
45 private final static Logger LOG = Log.getLogger(ClientUpgradeRequest.class);
46 private final static int MAX_KEYS = -1;
47 private static final Set<String> FORBIDDEN_HEADERS;
48
49 static
50 {
51
52 FORBIDDEN_HEADERS = new HashSet<>();
53 FORBIDDEN_HEADERS.add("cookie");
54 FORBIDDEN_HEADERS.add("upgrade");
55 FORBIDDEN_HEADERS.add("host");
56 FORBIDDEN_HEADERS.add("connection");
57 FORBIDDEN_HEADERS.add("sec-websocket-key");
58 FORBIDDEN_HEADERS.add("sec-websocket-extensions");
59 FORBIDDEN_HEADERS.add("sec-websocket-accept");
60 FORBIDDEN_HEADERS.add("sec-websocket-protocol");
61 FORBIDDEN_HEADERS.add("sec-websocket-version");
62 FORBIDDEN_HEADERS.add("pragma");
63 FORBIDDEN_HEADERS.add("cache-control");
64 }
65
66 private final String key;
67
68 public ClientUpgradeRequest()
69 {
70 super();
71 this.key = genRandomKey();
72 }
73
74 protected ClientUpgradeRequest(URI requestURI)
75 {
76 super(requestURI);
77 this.key = genRandomKey();
78 }
79
80 public String generate()
81 {
82 URI uri = getRequestURI();
83
84 StringBuilder request = new StringBuilder(512);
85 request.append("GET ");
86 if (StringUtil.isBlank(uri.getPath()))
87 {
88 request.append("/");
89 }
90 else
91 {
92 request.append(uri.getPath());
93 }
94 if (StringUtil.isNotBlank(uri.getRawQuery()))
95 {
96 request.append("?").append(uri.getRawQuery());
97 }
98 request.append(" HTTP/1.1\r\n");
99
100 request.append("Host: ").append(uri.getHost());
101 if (uri.getPort() > 0)
102 {
103 request.append(':').append(uri.getPort());
104 }
105 request.append("\r\n");
106
107
108 request.append("Upgrade: websocket\r\n");
109 request.append("Connection: Upgrade\r\n");
110 request.append("Sec-WebSocket-Key: ").append(key).append("\r\n");
111 request.append("Sec-WebSocket-Version: 13\r\n");
112
113
114
115
116
117 request.append("Pragma: no-cache\r\n");
118 request.append("Cache-Control: no-cache\r\n");
119
120
121 if (!getExtensions().isEmpty())
122 {
123 request.append("Sec-WebSocket-Extensions: ");
124 boolean needDelim = false;
125 for (ExtensionConfig ext : getExtensions())
126 {
127 if (needDelim)
128 {
129 request.append(", ");
130 }
131 request.append(ext.getParameterizedName());
132 needDelim = true;
133 }
134 request.append("\r\n");
135 }
136
137
138 if (!getSubProtocols().isEmpty())
139 {
140 request.append("Sec-WebSocket-Protocol: ");
141 boolean needDelim = false;
142 for (String protocol : getSubProtocols())
143 {
144 if (needDelim)
145 {
146 request.append(", ");
147 }
148 request.append(protocol);
149 needDelim = true;
150 }
151 request.append("\r\n");
152 }
153
154
155 List<HttpCookie> cookies = getCookies();
156 if ((cookies != null) && (cookies.size() > 0))
157 {
158 request.append("Cookie: ");
159 boolean needDelim = false;
160 for (HttpCookie cookie : cookies)
161 {
162 if (needDelim)
163 {
164 request.append("; ");
165 }
166 request.append(cookie.toString());
167 needDelim = true;
168 }
169 request.append("\r\n");
170 }
171
172
173 for (String key : getHeaders().keySet())
174 {
175 if (FORBIDDEN_HEADERS.contains(key.toLowerCase()))
176 {
177 LOG.warn("Skipping forbidden header - {}",key);
178 continue;
179 }
180 request.append(key).append(": ");
181 request.append(getHeader(key));
182 request.append("\r\n");
183 }
184
185
186 request.append("\r\n");
187 return request.toString();
188 }
189
190 private final String genRandomKey()
191 {
192 byte[] bytes = new byte[16];
193 new Random().nextBytes(bytes);
194 return new String(B64Code.encode(bytes));
195 }
196
197 public String getKey()
198 {
199 return key;
200 }
201
202 public void setCookiesFrom(CookieStore cookieStore)
203 {
204 if (cookieStore == null)
205 {
206 return;
207 }
208
209 setCookies(cookieStore.get(getRequestURI()));
210 }
211
212 @Override
213 public void setRequestURI(URI uri)
214 {
215 super.setRequestURI(uri);
216
217
218 Map<String, String[]> pmap = new HashMap<>();
219
220 String query = uri.getQuery();
221
222 if (StringUtil.isNotBlank(query))
223 {
224 MultiMap<String> params = new MultiMap<String>();
225 UrlEncoded.decodeTo(uri.getQuery(),params,"UTF-8",MAX_KEYS);
226
227 for (String key : params.keySet())
228 {
229 List<String> values = params.getValues(key);
230 if (values == null)
231 {
232 pmap.put(key,new String[0]);
233 }
234 else
235 {
236 int len = values.size();
237 pmap.put(key,values.toArray(new String[len]));
238 }
239 }
240
241 super.setParameterMap(pmap);
242 }
243 }
244 }