Skip to content

Instantly share code, notes, and snippets.

@timclassic
Last active December 15, 2015 16:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timclassic/5287161 to your computer and use it in GitHub Desktop.
Save timclassic/5287161 to your computer and use it in GitHub Desktop.
Fix for "Misultin websocket hixie76 implementation doesn't work behind haproxy" (https://github.com/ostinelli/misultin/issues/98). Misultin is EOL'd, so I thought I'd paste my patch here.
diff --git a/src/misultin_websocket_draft-hixie-76.erl b/src/misultin_websocket_draft-hixie-76.erl
index 6bcd8e1..d691e97 100644
--- a/src/misultin_websocket_draft-hixie-76.erl
+++ b/src/misultin_websocket_draft-hixie-76.erl
@@ -70,9 +70,19 @@ check_websocket(Headers) ->
% ----------------------------------------------------------------------------------------------------------
-spec handshake(Req::#req{}, Headers::http_headers(), {Path::string(), Origin::string(), Host::string()}) -> iolist().
handshake(#req{socket = Sock, socket_mode = SocketMode, ws_force_ssl = WsForceSsl}, Headers, {Path, Origin, Host}) ->
- % build data
- Key1 = misultin_utility:header_get_value('Sec-WebSocket-Key1', Headers),
- Key2 = misultin_utility:header_get_value('Sec-WebSocket-Key2', Headers),
+ % prepare handhsake response
+ WsMode = case SocketMode of
+ ssl -> "wss";
+ http when WsForceSsl =:= true -> "wss"; % behind stunnel or similar, client is using ssl
+ http when WsForceSsl =:= false -> "ws"
+ end,
+ Handshake = ["HTTP/1.1 101 WebSocket Protocol Handshake\r\n",
+ "Upgrade: WebSocket\r\n",
+ "Connection: Upgrade\r\n",
+ "Sec-WebSocket-Origin: ", Origin, "\r\n",
+ "Sec-WebSocket-Location: ", WsMode, "://", lists:concat([Host, Path]), "\r\n\r\n"],
+ ok = misultin_socket:send(Sock, Handshake, SocketMode),
+
% handshake needs body of the request, still need to read it [TODO: default recv timeout hard set, will be exported when WS protocol is final]
misultin_socket:setopts(Sock, [{packet, raw}, {active, false}], SocketMode),
Body = case misultin_socket:recv(Sock, 8, 30*1000, SocketMode) of
@@ -84,13 +94,12 @@ handshake(#req{socket = Sock, socket_mode = SocketMode, ws_force_ssl = WsForceSs
?LOG_ERROR("tcp error treating data: ~p", [_Other]),
<<>>
end,
- ?LOG_DEBUG("got content in body of websocket request: ~p", [Body]),
- % prepare handhsake response
- WsMode = case SocketMode of
- ssl -> "wss";
- http when WsForceSsl =:= true -> "wss"; % behind stunnel or similar, client is using ssl
- http when WsForceSsl =:= false -> "ws"
- end,
+ ?LOG_DEBUG("got content in body of websocket request: ~p", [Body]),
+
+ % build data
+ Key1 = misultin_utility:header_get_value('Sec-WebSocket-Key1', Headers),
+ Key2 = misultin_utility:header_get_value('Sec-WebSocket-Key2', Headers),
+
% build challenge
Ikey1 = [D || D <- Key1, $0 =< D, D =< $9],
Ikey2 = [D || D <- Key2, $0 =< D, D =< $9],
@@ -100,14 +109,9 @@ handshake(#req{socket = Sock, socket_mode = SocketMode, ws_force_ssl = WsForceSs
Part2 = erlang:list_to_integer(Ikey2) div Blank2,
Ckey = <<Part1:4/big-unsigned-integer-unit:8, Part2:4/big-unsigned-integer-unit:8, Body/binary>>,
Challenge = erlang:md5(Ckey),
- % format
- ["HTTP/1.1 101 WebSocket Protocol Handshake\r\n",
- "Upgrade: WebSocket\r\n",
- "Connection: Upgrade\r\n",
- "Sec-WebSocket-Origin: ", Origin, "\r\n",
- "Sec-WebSocket-Location: ", WsMode, "://", lists:concat([Host, Path]), "\r\n\r\n",
- Challenge
- ].
+
+ % return challenge
+ [Challenge].
% ----------------------------------------------------------------------------------------------------------
% Function: -> websocket_close | {websocket_close, DataToSendBeforeClose::binary() | iolist()} | NewState
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment