0
Fork 0
mirror of https://github.com/ninenines/cowboy.git synced 2025-07-14 12:20:24 +00:00

Don't discard data following a Websocket upgrade request

While the protocol does not allow sending data before
receiving a successful Websocket upgrade response, we
do not want to discard that data if it does come in.
This commit is contained in:
Loïc Hoguin 2019-10-05 13:04:21 +02:00
parent 618c001291
commit c50d6aa09c
No known key found for this signature in database
GPG key ID: 8A9DF795F6FED764
4 changed files with 81 additions and 60 deletions

View file

@ -602,9 +602,8 @@ sys_get_state_h1(Config) ->
{ok, Socket} = gen_tcp:connect("localhost", config(clear_port, Config), []),
timer:sleep(100),
Pid = get_remote_pid_tcp(Socket),
{State, Buffer} = sys:get_state(Pid),
State = sys:get_state(Pid),
state = element(1, State),
true = is_binary(Buffer),
ok.
sys_get_state_h2(Config) ->
@ -726,9 +725,8 @@ sys_replace_state_h1(Config) ->
{ok, Socket} = gen_tcp:connect("localhost", config(clear_port, Config), []),
timer:sleep(100),
Pid = get_remote_pid_tcp(Socket),
{State, Buffer} = sys:replace_state(Pid, fun(S) -> S end),
State = sys:replace_state(Pid, fun(S) -> S end),
state = element(1, State),
true = is_binary(Buffer),
ok.
sys_replace_state_h2(Config) ->

View file

@ -304,6 +304,18 @@ do_ws_deflate_opts_z(Path, Config) ->
{error, closed} = gen_tcp:recv(Socket, 0, 6000),
ok.
ws_first_frame_with_handshake(Config) ->
doc("Client sends the first frame immediately with the handshake. "
"This is invalid according to the protocol but we still want "
"to accept it if the handshake is successful."),
Mask = 16#37fa213d,
MaskedHello = do_mask(<<"Hello">>, Mask, <<>>),
{ok, Socket, _} = do_handshake("/ws_echo", "",
<<1:1, 0:3, 1:4, 1:1, 5:7, Mask:32, MaskedHello/binary>>,
Config),
{ok, <<1:1, 0:3, 1:4, 0:1, 5:7, "Hello">>} = gen_tcp:recv(Socket, 0, 6000),
ok.
ws_init_return_ok(Config) ->
doc("Handler does nothing."),
{ok, Socket, _} = do_handshake("/ws_init?ok", Config),
@ -636,9 +648,12 @@ ws_webkit_deflate_single_bytes(Config) ->
%% Internal.
do_handshake(Path, Config) ->
do_handshake(Path, "", Config).
do_handshake(Path, "", "", Config).
do_handshake(Path, ExtraHeaders, Config) ->
do_handshake(Path, ExtraHeaders, "", Config).
do_handshake(Path, ExtraHeaders, ExtraData, Config) ->
{ok, Socket} = gen_tcp:connect("localhost", config(port, Config),
[binary, {active, false}]),
ok = gen_tcp:send(Socket, [
@ -650,10 +665,16 @@ do_handshake(Path, ExtraHeaders, Config) ->
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
"Upgrade: websocket\r\n",
ExtraHeaders,
"\r\n"]),
"\r\n",
ExtraData]),
{ok, Handshake} = gen_tcp:recv(Socket, 0, 6000),
{ok, {http_response, {1, 1}, 101, _}, Rest} = erlang:decode_packet(http, Handshake, []),
[Headers, <<>>] = do_decode_headers(erlang:decode_packet(httph, Rest, []), []),
[Headers, Data] = do_decode_headers(erlang:decode_packet(httph, Rest, []), []),
%% Queue extra data back, if any. We don't want to receive it yet.
case Data of
<<>> -> ok;
_ -> gen_tcp:unrecv(Socket, Data)
end,
{_, "Upgrade"} = lists:keyfind('Connection', 1, Headers),
{_, "websocket"} = lists:keyfind('Upgrade', 1, Headers),
{_, "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="} = lists:keyfind("sec-websocket-accept", 1, Headers),