I've been having this problem for months now, and I've scrolled all over the web, and got no answer. Right now, I am running Yaws version 2.0.6, and Erlang OTP 19 for my project. I know to establish a websocket connection, the client needs to make a request to the server for a handshake. I have my client side written in javascript, and my server side written in erlang. However, when I try to run the program, I get this vague Yaws error message stating, "Invalid connection header". It doesn't tell me specifically what I need to change, but somehow I have a feeling it has one or two things to do with the header. Number one, the header somehow didn't upgrade from http protocol to websocket correctly, or two, there is something wrong with websocket connection. I don't know what it is, but I'll show you the snippets of code on both sides, plus the error message, and if you can show me a different way of writing code for either side, that would be very helpful. Thanks.
Client side!!!
$(function() {
var WebSocket = window.WebSocket || window.MozWebSocket;
var socket = new WebSocket("ws://127.0.0.1:8080/sign_up.yaws");
// wait for socket to open
socket.onopen = function() {
$('input#echo').on('keypress', function(event) {
if (event.which == 13) {
event.preventDefault();
var msg = $(this).val();
socket.send(JSON.stringify({
message: msg
}));
}
});
socket.onmessage = function(msg) {
var message = $.parseJSON(msg.data);
var html = $('div#messages').html() + message.message + "<br>\n";
$('div#message').html(html);
}
}
});
server-side
-module(sign_up).
-include("yaws_api.hrl").
-export([handle_message/2]).
-record(state, {frag_type = none,
acc = <<>>}).
handle_message(#ws_frame_info{fin=0,
opcode=FragType,
data=Data},
#state{frag_type=none, acc = <<>>}) ->
{noreply, #state{frag_type=FragType, acc=Data}};
handle_message(#ws_frame_info{fin=0,
opcode=continuation,
data=Data},
#state{frag_type = FragType, acc = Acc}) ->
{noreply, #state{frag_type=FragType, acc = <<Acc/binary,Data/binary>>}};
handle_message(#ws_frame_info{fin=1,
opcode=continuation,
data=Data},
#state{frag_type=text, acc=Acc}) ->
Unfragged = <<Acc/binary, Data/binary>>,
{reply, {text, Unfragged}, #state{frag_type=none, acc = <<>>}};
handle_message(#ws_frame_info{opcode=text, data=Data}, State) ->
{reply, {text, Data}, State};
handle_message(#ws_frame_info{fin=1,
opcode=continuation,
data=Data},
#state{frag_type=binary, acc=Acc}) ->
Unfragged = <<Acc/binary, Data/binary>>,
io:format("echoing back binary message~n", []),
{reply, {binary, Unfragged}, #state{frag_type=none, acc = <<>>}};
handle_message(#ws_frame_info{opcode=binary,
data=Data},
State) ->
io:format("echoing back binary message~n", []),
{reply, {binary, Data}, State};
handle_message(#ws_frame_info{opcode=pong}, State) ->
io:format("ignoring unsolicited pong~n", []),
{noreply, State};
handle_message(#ws_frame_info{}=FrameInfo, State) ->
io:format("WS Endpoint Unhandled message: ~p~n~p~n", [FrameInfo, State]),
{close, {error, {unhandled_message, FrameInfo}}}.
html
<script language="Javascript" type="text/javascript" src="jquery.min.map"></script><script language="Javascript" type="text/javascript" src="socket.js"></script>
<erl>
get_upgrade_header(#headers{other=L}) ->
lists:foldl(fun({http_header,_,KO,_,V}, undefined) ->
K = case is_atom(KO) of
true ->
atom_to_list(KO);
false ->
KO
end,
case string:to_lower(K) of
"upgrade" ->
true;
_ ->
false
end;
(_, ACC) ->
ACC
end, undefined, L).
%%------------------------------------------------------------------------------
out(Arg) ->
case get_upgrade_header(Arg#arg.headers) of
true ->
error_logger:warning_msg("Not a web socket client~n"),
{content, "text/plain", "You're not a web sockets client! Go away!"};
false ->
error_logger:info_msg("Starting web socket~n"),
{websocket, sign_up, []}
end.
</erl>
Yaws code crashed error message
=INFO REPORT==== 13-Jan-2022::15:04:24 ===
Starting web socket
=ERROR REPORT==== 13-Jan-2022::15:04:24 ===
Invalid connection header
I know I've asked this question before, and I'm sorry for asking again. I don't think I was as explicit before as I am today, but if anyone can show me a different way to solve this problem, like rewrite the server side code, or do some editing to the erlang code on the html page, I would very appreciate it. Thanks again.