Просмотр исходного кода

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 лет назад
Родитель
Сommit
381c178073
2 измененных файлов с 20 добавлено и 10 удалено
  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, <<>>).