Browse Source

Add a cowboy_http_req:upgrade_reply/3 function and use it for websockets

This function doesn't try to add any additional header besides the
Connection: Upgrade header. It also doesn't accept a body.

It should be used for the intermediate reply to an upgrade process,
before the real reply is sent (if any, for example when using TLS).
Loïc Hoguin 13 years ago
parent
commit
381c178073
2 changed files with 20 additions and 10 deletions
  1. 13 1
      src/cowboy_http_req.erl
  2. 7 9
      src/cowboy_http_websocket.erl

+ 13 - 1
src/cowboy_http_req.erl

@@ -38,7 +38,8 @@
 
 -export([
 	reply/2, reply/3, reply/4,
-	chunked_reply/2, chunked_reply/3, chunk/2
+	chunked_reply/2, chunked_reply/3, chunk/2,
+	upgrade_reply/3
 ]). %% Response API.
 
 -export([
@@ -374,6 +375,17 @@ chunk(Data, #http_req{socket=Socket, transport=Transport, resp_state=chunks}) ->
 	Transport:send(Socket, [integer_to_list(iolist_size(Data), 16),
 		<<"\r\n">>, Data, <<"\r\n">>]).
 
+%% @doc Send an upgrade reply.
+-spec upgrade_reply(http_status(), http_headers(), #http_req{})
+	-> {ok, #http_req{}}.
+upgrade_reply(Status, Headers, Req=#http_req{socket=Socket, transport=Transport,
+		resp_state=waiting}) ->
+	Head = response_head(Status, Headers, [
+		{<<"Connection">>, <<"Upgrade">>}
+	]),
+	Transport:send(Socket, Head),
+	{ok, Req#http_req{resp_state=done}}.
+
 %% Misc API.
 
 %% @doc Compact the request data by removing all non-system information.

+ 7 - 9
src/cowboy_http_websocket.erl

@@ -170,13 +170,12 @@ websocket_handshake(State=#state{version=0, origin=Origin,
 		transport=Transport, raw_host=Host, port=Port,
 		raw_path=Path, raw_qs=QS}, HandlerState) ->
 	Location = hixie76_location(Transport:name(), Host, Port, Path, QS),
-	{ok, Req2} = cowboy_http_req:reply(
+	{ok, Req2} = cowboy_http_req:upgrade_reply(
 		<<"101 WebSocket Protocol Handshake">>,
-		[{<<"Connection">>, <<"Upgrade">>},
-		 {<<"Upgrade">>, <<"WebSocket">>},
+		[{<<"Upgrade">>, <<"WebSocket">>},
 		 {<<"Sec-Websocket-Location">>, Location},
 		 {<<"Sec-Websocket-Origin">>, Origin}],
-		[], Req#http_req{resp_state=waiting}),
+		Req#http_req{resp_state=waiting}),
 	%% We replied with a proper response. Proxies should be happy enough,
 	%% we can now read the 8 last bytes of the challenge keys and send
 	%% the challenge response directly to the socket.
@@ -187,12 +186,11 @@ websocket_handshake(State=#state{version=0, origin=Origin,
 		Req3, HandlerState, <<>>);
 websocket_handshake(State=#state{challenge=Challenge},
 		Req=#http_req{transport=Transport}, HandlerState) ->
-	{ok, Req2} = cowboy_http_req:reply(
-		<<"101 Switching Protocols">>,
-		[{<<"Connection">>, <<"Upgrade">>},
-		 {<<"Upgrade">>, <<"websocket">>},
+	{ok, Req2} = cowboy_http_req:upgrade_reply(
+		101,
+		[{<<"Upgrade">>, <<"websocket">>},
 		 {<<"Sec-Websocket-Accept">>, Challenge}],
-		[], Req#http_req{resp_state=waiting}),
+		Req#http_req{resp_state=waiting}),
 	handler_before_loop(State#state{messages=Transport:messages()},
 		Req2, HandlerState, <<>>).