You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ro...@apache.org on 2015/06/29 23:46:37 UTC
[31/50] couch commit: updated refs/heads/COUCHDB-2734-header-date to
f3e022c
add HTML for example
Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/ecee927a
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/ecee927a
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/ecee927a
Branch: refs/heads/COUCHDB-2734-header-date
Commit: ecee927a04a51858677cd13def37f575ebbb33e7
Parents: 8ecae10
Author: Bob Ippolito <bo...@redivi.com>
Authored: Wed Dec 25 15:06:50 2013 -0800
Committer: Bob Ippolito <bo...@redivi.com>
Committed: Wed Dec 25 15:06:50 2013 -0800
----------------------------------------------------------------------
.gitignore | 2 +
examples/websocket/index.html | 59 +++++++++++++++++
examples/websocket/websocket.erl | 121 ++++++++++++++++++----------------
src/mochiweb_websocket.erl | 10 ++-
4 files changed, 135 insertions(+), 57 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/ecee927a/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 09f877f..8f4edf4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,5 @@
/TEST-*.xml
/deps
*.swp
+*.beam
+*.dump
http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/ecee927a/examples/websocket/index.html
----------------------------------------------------------------------
diff --git a/examples/websocket/index.html b/examples/websocket/index.html
new file mode 100644
index 0000000..6926aba
--- /dev/null
+++ b/examples/websocket/index.html
@@ -0,0 +1,59 @@
+<!doctype html>
+<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">
+ <form id="sendForm">
+ <input id="phrase" type="text"/>
+ <input id="btnSend" class="button" type="submit" name="connect"
+ value="Send"/>
+ </form>
+ </div>
+ <hr/>
+ <div id="msgs"></div>
+
+ <script type="text/javascript">
+ var ws;
+ if (!window.WebSocket) {
+ alert("WebSocket not supported by this browser");
+ }
+ function $(id) {
+ return document.getElementById(id);
+ }
+ function go() {
+ ws = new WebSocket("ws://" + location.host + "/");
+ ws.onopen = function () {
+ $('connstate').innerHTML = 'CONNECTED';
+ }
+ ws.onclose = function () {
+ $('connstate').innerHTML = 'CLOSED';
+ }
+ ws.onmessage = function (e) {
+ var p = document.createElement('pre');
+ p.appendChild(document.createTextNode(e.data));
+ $('msgs').appendChild(p);
+ }
+ }
+ $('sendForm').onsubmit = function (event) {
+ var p = $('phrase');
+ ws.send(p.value);
+ p.value='';
+ return false;
+ }
+ $('btnConn').onclick = function(event) {
+ go(); return false;
+ };
+ </script>
+ </body>
+</html>
+
http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/ecee927a/examples/websocket/websocket.erl
----------------------------------------------------------------------
diff --git a/examples/websocket/websocket.erl b/examples/websocket/websocket.erl
index b392a20..4049941 100644
--- a/examples/websocket/websocket.erl
+++ b/examples/websocket/websocket.erl
@@ -1,82 +1,93 @@
-module(websocket).
-% The MIT License (MIT)
+%% To run: erlc websocket.erl && erl -pa ../../ebin -s websocket
+
+%% The MIT License (MIT)
%% Copyright (c) 2012 Zadane.pl sp. z o.o.
-% Permission is hereby granted, free of charge, to any person obtaining a copy
-% of this software and associated documentation files (the "Software"), to deal
-% in the Software without restriction, including without limitation the rights
-% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-% copies of the Software, and to permit persons to whom the Software is
-% furnished to do so, subject to the following conditions:
+%% Permission is hereby granted, free of charge, to any person obtaining a copy
+%% of this software and associated documentation files (the "Software"), to deal
+%% in the Software without restriction, including without limitation the rights
+%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+%% copies of the Software, and to permit persons to whom the Software is
+%% furnished to do so, subject to the following conditions:
-% The above copyright notice and this permission notice shall be included in
-% all copies or substantial portions of the Software.
+%% The above copyright notice and this permission notice shall be included in
+%% all copies or substantial portions of the Software.
-% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-% THE SOFTWARE.
+%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+%% THE SOFTWARE.
--export([start_link/0, ws_loop/3, loop/1]).
+-export([start/0, start_link/0, ws_loop/3, loop/1]).
-%
-% Mochiweb websocket example
-%
-% [1]: At first you have to start HTTP server which will listen for HTTP requests
-% and eventually upgrade connection to websocket
-% [2]: Attempt to upgrade connection to websocket.
-% Function mochiweb_websocket:upgrade_connection/2:
-% * first argument is mochiweb_request
-% * second is M:F which will handle further websocket messages.
-% Function return two funs:
-% * ReentryWs/1 - use it to enter to messages handling loop (in this example ws_loop/3)
-% * ReplyChannel/1 - use to send messages to client. May be passed to other processes
-% [3]: Example of sending message to client
-% [4]: State that will be passed to message handling loop
-% [5]: Pass controll to messages handling loop. From this moment each message received from client
-% can be handled...
-% [6]: ...here as Payload. State is variable intended for holiding your custom state. ReplyChannel
-% is the same function as in [3].
-% Notice! Payload is list of messages received from client. Websocket framing mechanism
-% concatenates messages which are sent one after another in short time.
-% [7]: Print payload received from client and send it back
-% [8]: Message handling function must return new state value
-start_link() ->
- % [1]
- Loop = fun (Req) ->
- ?MODULE:loop(Req)
- end,
+%%
+%% Mochiweb websocket example
+%%
+%% [1]: At first you have to start HTTP server which will listen for HTTP
+%% requests and eventually upgrade connection to websocket
+%% [2]: Attempt to upgrade connection to websocket.
+%% Function mochiweb_websocket:upgrade_connection/2:
+%% * first argument is mochiweb_request
+%% * second is M:F which will handle further websocket messages.
+%% Function return two funs:
+%% * ReentryWs/1 - use it to enter to messages handling loop
+%% (in this example ws_loop/3)
+%% * ReplyChannel/1 - use to send messages to client. May be passed to
+%% other processes
+%% [3]: Example of sending message to client
+%% [4]: State that will be passed to message handling loop
+%% [5]: Pass control to messages handling loop. From this moment each message
+%% received from client can be handled...
+%% [6]: ...here as Payload. State is variable intended for holding your custom
+%% state. ReplyChannel is the same function as in [3].
+%% Notice! Payload is list of messages received from client. Websocket
+%% framing mechanism concatenates messages which are sent one after another
+%% in short time.
+%% [7]: Print payload received from client and send it back
+%% [8]: Message handling function must return new state value
+start() ->
+ application:start(sasl),
+ start_link(),
+ erlang:hibernate(?MODULE, start, []).
+start_link() ->
+ %% [1]
+ io:format("Listening at http://127.0.0.1:8080/~n"),
mochiweb_http:start_link([
- {name, client_access},
- {loop, Loop},
+ {name, client_access},
+ {loop, fun ?MODULE:loop/1},
{port, 8080}
]).
ws_loop(Payload, State, ReplyChannel) ->
- % [6]
+ %% [6]
- % [7]
+ %% [7]
io:format("Received data: ~p~n", [Payload]),
Received = list_to_binary(Payload),
ReplyChannel(<<"Received ", Received/binary>>),
- % [8]
+ %% [8]
State.
loop(Req) ->
- % [2]
- {ReentryWs, ReplyChannel} = mochiweb_websocket:upgrade_connection(Req, {?MODULE, ws_loop}),
+ H = mochiweb_request:get_header_value("Upgrade", Req),
+ loop(Req, H =/= undefined andalso string:to_lower(H) =:= "websocket").
- % [3]
+loop(Req, false) ->
+ mochiweb_request:serve_file("index.html", "./", Req);
+loop(Req, true) ->
+ {ReentryWs, ReplyChannel} = mochiweb_websocket:upgrade_connection(
+ Req, fun ?MODULE:ws_loop/3),
+ %% [3]
ReplyChannel(<<"Hello">>),
-
- % [4]
+ %% [4]
InitialState = [],
- % [5]
+ %% [5]
ReentryWs(InitialState).
http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/ecee927a/src/mochiweb_websocket.erl
----------------------------------------------------------------------
diff --git a/src/mochiweb_websocket.erl b/src/mochiweb_websocket.erl
index 1880f86..8309a11 100644
--- a/src/mochiweb_websocket.erl
+++ b/src/mochiweb_websocket.erl
@@ -45,7 +45,6 @@ request(Socket, Body, State, WsVersion, ReplyChannel) ->
exit(normal);
{tcp, _, WsFrames} ->
- {M, F} = Body,
case parse_frames(WsVersion, WsFrames, Socket) of
close ->
mochiweb_socket:close(Socket),
@@ -56,7 +55,7 @@ request(Socket, Body, State, WsVersion, ReplyChannel) ->
exit(normal);
Payload ->
- NewState = M:F(Payload, State, ReplyChannel),
+ NewState = call_body(Body, Payload, State, ReplyChannel),
loop(Socket, Body, NewState, WsVersion, ReplyChannel)
end;
@@ -65,6 +64,13 @@ request(Socket, Body, State, WsVersion, ReplyChannel) ->
exit(normal)
end.
+call_body({M, F, A}, Payload, State, ReplyChannel) ->
+ erlang:apply(M, F, [Payload, State, ReplyChannel | A]);
+call_body({M, F}, Payload, State, ReplyChannel) ->
+ M:F(Payload, State, ReplyChannel);
+call_body(Body, Payload, State, ReplyChannel) ->
+ Body(Payload, State, ReplyChannel).
+
send(Socket, Payload, hybi) ->
Len = payload_length(iolist_size(Payload)),
Data = <<1:1, 0:3, 1:4, 0:1, Len/bits, Payload/binary>>,