2323import org .apache .http .Header ;
2424import org .apache .http .HttpStatus ;
2525import org .apache .http .ParseException ;
26+ import org .apache .http .ProtocolVersion ;
2627import org .apache .http .StatusLine ;
28+ import org .apache .http .message .BasicHeader ;
29+ import org .apache .http .message .BasicLineFormatter ;
2730import org .apache .http .message .BasicLineParser ;
31+ import org .apache .http .message .BasicRequestLine ;
32+ import org .apache .http .message .LineFormatter ;
33+ import org .apache .http .util .CharArrayBuffer ;
2834import org .apache .http .util .EncodingUtils ;
2935
3036import java .io .IOException ;
@@ -83,6 +89,10 @@ private enum State {
8389 @ Nonnull
8490 private final URI uri ;
8591 @ Nonnull
92+ private final List <String > subProtocols ;
93+ @ Nonnull
94+ private final List <Header > headers ;
95+ @ Nonnull
8696 private final SecureRandomProvider secureRandomProvider ;
8797
8898
@@ -98,15 +108,19 @@ private enum State {
98108 private int writing = 0 ;
99109
100110 /**
101- * @see NewWebSocket#create(URI, WebSocketListener)
102- */
103- WebSocketConnection (@ Nonnull Socket socket ,
104- @ Nonnull WebSocketListener listener ,
105- @ Nonnull URI uri ,
106- @ Nonnull SecureRandomProvider secureRandomProvider ) {
111+ * @see NewWebSocket#create(URI, List, List, WebSocketListener)
112+ */
113+ WebSocketConnection (@ Nonnull Socket socket ,
114+ @ Nonnull WebSocketListener listener ,
115+ @ Nonnull URI uri ,
116+ @ Nonnull List <String > subProtocols ,
117+ @ Nonnull List <Header > headers ,
118+ @ Nonnull SecureRandomProvider secureRandomProvider ) {
107119 this .socket = socket ;
108120 this .listener = listener ;
109121 this .uri = uri ;
122+ this .subProtocols = subProtocols ;
123+ this .headers = headers ;
110124 this .secureRandomProvider = secureRandomProvider ;
111125 }
112126
@@ -138,7 +152,7 @@ public void connect() throws WrongWebsocketResponse,
138152 outputStream = new WebSocketWriter (socket .getOutputStream ());
139153 }
140154 final String secret = generateHandshakeSecret ();
141- writeHeaders (uri , secret );
155+ writeHeaders (uri , secret , subProtocols , headers );
142156 readHandshakeHeaders (inputStream , secret );
143157 } catch (IOException e ) {
144158 synchronized (stateLock ) {
@@ -210,21 +224,43 @@ private String generateHandshakeSecret() {
210224 *
211225 * @param uri uri
212226 * @param secret secret that is written to headers
227+ * @param subProtocols application-level protocols layered over the WebSocket Protocol
228+ * @param headers headers sent to server
213229 * @throws IOException
214230 */
215- private void writeHeaders (@ Nonnull URI uri , @ Nonnull String secret ) throws IOException {
231+ private void writeHeaders (@ Nonnull URI uri ,
232+ @ Nonnull String secret ,
233+ @ Nonnull List <String > subProtocols ,
234+ @ Nonnull List <Header > headers )
235+ throws IOException {
216236 checkNotNull (uri );
217237 checkNotNull (secret );
238+ checkNotNull (subProtocols );
239+ checkArgument (subProtocols .size () >= 0 , "You have to provide at least one subProtocol" );
240+ checkNotNull (headers );
218241 final String portPart = uri .getPort () < 0 || uri .getPort () == 80 ? "" : ":" +String .valueOf (uri .getPort ());
219242
220- outputStream .writeLine ("GET " + uri .getPath () + " HTTP/1.1" );
221- outputStream .writeLine ("Upgrade: websocket" );
222- outputStream .writeLine ("Connection: Upgrade" );
223- outputStream .writeLine ("Host: " + uri .getHost ()+portPart );
224- outputStream .writeLine ("Origin: " + uri );
225- outputStream .writeLine ("Sec-WebSocket-Key: " + secret );
226- outputStream .writeLine ("Sec-WebSocket-Protocol: chat" );
227- outputStream .writeLine ("Sec-WebSocket-Version: 13" );
243+ final BasicRequestLine requestLine = new BasicRequestLine ("GET" , uri .getPath (), new ProtocolVersion ("HTTP" , 1 , 1 ));
244+
245+ final ArrayList <Header > sentHeaders = new ArrayList <>();
246+ sentHeaders .add (new BasicHeader ("Upgrade" , "websocket" ));
247+ sentHeaders .add (new BasicHeader ("Connection" , "Upgrade" ));
248+ sentHeaders .add (new BasicHeader ("Host" , uri .getHost () + portPart ));
249+ sentHeaders .add (new BasicHeader ("Origin" , uri .toString ()));
250+ sentHeaders .add (new BasicHeader ("Sec-WebSocket-Key" , secret ));
251+ for (final String subProtocol : subProtocols ) {
252+ sentHeaders .add (new BasicHeader ("Sec-WebSocket-Protocol" , subProtocol ));
253+ }
254+ sentHeaders .add (new BasicHeader ("Sec-WebSocket-Version" , "13" ));
255+ sentHeaders .addAll (headers );
256+
257+ final LineFormatter lineFormatter = BasicLineFormatter .INSTANCE ;
258+ final CharArrayBuffer buffer = new CharArrayBuffer (100 );
259+ outputStream .writeLine (lineFormatter .formatRequestLine (buffer , requestLine ).toString ());
260+ for (final Header header : sentHeaders ) {
261+ outputStream .writeLine (lineFormatter .formatHeader (buffer , header ).toString ());
262+ }
263+
228264 outputStream .writeNewLine ();
229265 outputStream .flush ();
230266 }
0 commit comments