Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
support upgrading connections to websockets, provide async websocket …
…api, support websockets over https, create websockets demo
- Loading branch information
Showing
6 changed files
with
469 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<html> | ||
<head> | ||
<title>Websockets With Mochiweb Demo</title> | ||
</head> | ||
<body> | ||
<h1>Mochiweb websocket demo</h1> | ||
|
||
<div id="connect"> | ||
<button id="btnConn">Connect</button> | ||
State: <span id="connstate" style="font-weight:bold;"></span> | ||
</div> | ||
<br/><i>Protip: open your javascript error console, just in case..</i><br/> | ||
<hr/> | ||
<div id="connected"> | ||
<input id='phrase' type='text'/> | ||
<input id='btnSend' class='button' type='submit' name='connect' value='Send'/> | ||
</div> | ||
<hr/> | ||
<div id="msgs"></div> | ||
|
||
<script type="text/javascript"> | ||
var ws; | ||
if (!window.WebSocket) alert("WebSocket not supported by this browser"); | ||
function $() { return document.getElementById(arguments[0]); } | ||
function go() | ||
{ | ||
ws = new WebSocket("wss://localhost:8080/"); | ||
ws.onopen = function(){ $('connstate').innerHTML='CONNECTED'; } | ||
ws.onclose = function(){ $('connstate').innerHTML='CLOSED'; } | ||
ws.onmessage = function(e){ $('msgs').innerHTML = $('msgs').innerHTML + "<pre>"+e.data+"</pre>"; } | ||
} | ||
|
||
$('btnConn').onclick = function(event) { go(); return false; }; | ||
$('btnSend').onclick = function(event) { ws.send($('phrase').value); $('phrase').value=''; return false; }; | ||
|
||
</script> | ||
</body> | ||
</html> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
-module(websockets_demo). | ||
-author('author <rj@metabrew.com>'). | ||
|
||
-export([start/0, start/1, stop/0, loop/2, wsloop_active/1]). | ||
|
||
start() -> start([{port, 8080}, {docroot, "."}]). | ||
|
||
start(Options) -> | ||
{DocRoot, Options1} = get_option(docroot, Options), | ||
Loop = fun (Req) -> ?MODULE:loop(Req, DocRoot) end, | ||
% How we validate origin for cross-domain checks: | ||
OriginValidator = fun(Origin) -> | ||
io:format("Origin '~s' -> OK~n", [Origin]), | ||
true | ||
end, | ||
% websocket options | ||
WsOpts = [ {active, true}, | ||
{origin_validator, OriginValidator}, | ||
{loop, {?MODULE, wsloop_active}} ], | ||
% | ||
Ssl = [ {ssl, true}, {ssl_opts, [ {certfile, "../https/server_cert.pem"}, | ||
{keyfile, "../https/server_key.pem"}]} ], | ||
% | ||
mochiweb_http:start([{name, ?MODULE}, | ||
{loop, Loop}, | ||
{websocket_opts, WsOpts} | Options1] ++ Ssl). | ||
|
||
stop() -> | ||
mochiweb_http:stop(?MODULE). | ||
|
||
wsloop_active(WSReq) -> | ||
% assuming you set a "session" cookie as part of your http login stuff | ||
io:format("session cookie: ~p~n", [WSReq:get_cookie_value("session")]), | ||
WSReq:send("WELCOME MSG FROM THE SERVER!"), | ||
% send some misc info to demonstrate the WSReq API | ||
Info = [ "Here's what the server knows about the connection:", | ||
"\nget(peername) = " , io_lib:format("~p",[WSReq:get(peername)]), | ||
"\nget(path) = " , io_lib:format("~p",[WSReq:get(path)]), | ||
"\nget(type) = " , io_lib:format("~p",[WSReq:get(type)]), | ||
"\nget(headers) = " , io_lib:format("~p",[WSReq:get(headers)]) ], | ||
WSReq:send(Info), | ||
wsloop_active0(WSReq). | ||
|
||
wsloop_active0(WSReq) -> | ||
receive | ||
closed -> | ||
io:format("client api got closed~n",[]), | ||
ok; | ||
{error, Reason} -> | ||
io:format("client api got error ~p~n", [Reason]), | ||
ok; | ||
{frame, Frame} -> | ||
Msg = ["Dear client, thanks for sending us this msg: ", Frame], | ||
WSReq:send(Msg), | ||
wsloop_active0(WSReq) | ||
after 15000 -> | ||
WSReq:send("IDLE!"), | ||
wsloop_active0(WSReq) | ||
end. | ||
|
||
loop(Req, DocRoot) -> | ||
"/" ++ Path = Req:get(path), | ||
case Req:get(method) of | ||
Method when Method =:= 'GET'; Method =:= 'HEAD' -> | ||
case Path of | ||
_ -> | ||
Req:serve_file(Path, DocRoot) | ||
end; | ||
'POST' -> | ||
case Path of | ||
_ -> | ||
Req:not_found() | ||
end; | ||
_ -> | ||
Req:respond({501, [], []}) | ||
end. | ||
|
||
%% Internal API | ||
|
||
get_option(Option, Options) -> | ||
{proplists:get_value(Option, Options), proplists:delete(Option, Options)}. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Spelling error in undefined atom. ;) Any reason not to use Origin =/= undefined?