forked from tOkeshu/cowboy_examples
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
add5fa5
commit ae4439c
Showing
8 changed files
with
323 additions
and
1 deletion.
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,6 @@ | ||
log/* | ||
ebin/*.beam | ||
ebin/*.app | ||
erl_crash.dump | ||
!.gitignore | ||
deps |
Empty file.
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,42 @@ | ||
<html><head> | ||
<title>Bullet Awesomeness!</title> | ||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script> | ||
<script src="bullet.js" type="text/javascript"></script> | ||
<script> | ||
$(document).ready(function(){ | ||
var bullet = $.bullet('ws://localhost:8080/bullet'); | ||
bullet.onopen = function(){ | ||
console.log('WebSocket: opened'); | ||
}; | ||
bullet.onclose = function(){ | ||
console.log('WebSocket: closed'); | ||
}; | ||
bullet.onmessage = function(e){ | ||
console.log(e.data); | ||
}; | ||
bullet.onheartbeat = function(){ | ||
bullet.send('ping'); | ||
}; | ||
|
||
$("#inputBox").focus(); | ||
|
||
// configure the Shout submit to publish a message | ||
$("#chatForm").submit(function(event){ | ||
// prevent the submit button from doing a POST and causing a page reload by returning false from the submit event | ||
bullet.send($('#inputBox').val()); | ||
return false; | ||
}); | ||
|
||
}); | ||
|
||
</script> | ||
</head> | ||
<body> | ||
<div id="inputArea"> | ||
<form id="chatForm" autocomplete="off"> | ||
<input type="text" name="inputBox" id="inputBox"> | ||
<input type="submit" class="submit" value="Fire!"> | ||
</form> | ||
</div> | ||
</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,247 @@ | ||
/* | ||
Copyright (c) 2011, Loïc Hoguin <essen@dev-extend.eu> | ||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted, provided that the above | ||
copyright notice and this permission notice appear in all copies. | ||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
*/ | ||
|
||
/** | ||
Bullet is a client-side javascript library AND server-side Cowboy handler | ||
to manage continuous streaming. It selects the proper transport in a fully | ||
automated way and makes sure to always reconnect to the server on any | ||
disconnect. You only need to handle sending messages, receiving them, | ||
and managing the heartbeat of the stream. | ||
Usage: $.bullet(url); | ||
Then you can register one of the 4 event handlers: | ||
onopen, onmessage, onclose, onheartbeat. | ||
onopen is called once right after starting the bullet stream. | ||
onmessage is called once for each message receveid. | ||
onclose is called once right after you voluntarily close the socket. | ||
onheartbeat is called once every few seconds to allow you to easily setup | ||
a ping/pong mechanism. | ||
*/ | ||
(function($){$.extend({bullet: function(url){ | ||
var CONNECTING = 0; | ||
var OPEN = 1; | ||
var CLOSING = 2; | ||
var CLOSED = 3; | ||
|
||
var transports = { | ||
/** | ||
The websocket transport is disabled for Firefox 6.0 because it | ||
causes a crash to happen when the connection is closed. | ||
@see https://bugzilla.mozilla.org/show_bug.cgi?id=662554 | ||
*/ | ||
websocket: function(){ | ||
var ret = false; | ||
|
||
if (window.WebSocket){ | ||
ret = window.WebSocket; | ||
} | ||
|
||
if (window.MozWebSocket | ||
&& navigator.userAgent.indexOf("Firefox/6.0") == -1){ | ||
ret = window.MozWebSocket; | ||
} | ||
|
||
if (ret){ | ||
return {'heart': true, 'transport': ret}; | ||
} | ||
|
||
return false; | ||
}, | ||
|
||
xhrPolling: function(){ | ||
var timeout; | ||
var xhr; | ||
|
||
var fake = { | ||
readyState: CONNECTING, | ||
send: function(data){ | ||
if (this.readyState != CONNECTING && this.readyState != OPEN){ | ||
return false; | ||
} | ||
|
||
var fakeurl = url.replace('ws:', 'http:').replace('wss:', 'https:'); | ||
|
||
$.ajax({ | ||
async: false, | ||
cache: false, | ||
type: 'POST', | ||
url: fakeurl, | ||
data: data, | ||
dataType: 'text', | ||
contentType: | ||
'application/x-www-form-urlencoded; charset=utf-8', | ||
headers: {'X-Socket-Transport': 'xhrPolling'}, | ||
success: function(data){ | ||
if (data.length != 0){ | ||
fake.onmessage({'data': data}); | ||
} | ||
} | ||
}); | ||
|
||
return true; | ||
}, | ||
close: function(){ | ||
this.readyState = CLOSED; | ||
xhr.abort(); | ||
clearTimeout(timeout); | ||
fake.onclose(); | ||
}, | ||
onopen: function(){}, | ||
onmessage: function(){}, | ||
onerror: function(){}, | ||
onclose: function(){} | ||
}; | ||
|
||
function poll(){ | ||
var fakeurl = url.replace('ws:', 'http:').replace('wss:', 'https:'); | ||
|
||
xhr = $.ajax({ | ||
type: 'GET', | ||
cache: false, | ||
url: fakeurl, | ||
dataType: 'text', | ||
data: {}, | ||
headers: {'X-Socket-Transport': 'xhrPolling'}, | ||
success: function(data){ | ||
if (fake.readyState == CONNECTING){ | ||
fake.readyState = OPEN; | ||
fake.onopen(fake); | ||
} | ||
// Connection might have closed without a response body | ||
if (data.length != 0){ | ||
fake.onmessage({'data': data}); | ||
} | ||
if (fake.readyState == OPEN){ | ||
nextPoll(); | ||
} | ||
}, | ||
error: function(xhr){ | ||
fake.onerror(); | ||
} | ||
}); | ||
} | ||
|
||
function nextPoll(){ | ||
timeout = setTimeout(function(){poll();}, 100); | ||
} | ||
|
||
nextPoll(); | ||
|
||
return {'heart': false, 'transport': function(){ return fake; }}; | ||
} | ||
}; | ||
|
||
var tn = 0; | ||
function next(){ | ||
var c = 0; | ||
|
||
for (var f in transports){ | ||
if (tn == c){ | ||
var t = transports[f](); | ||
if (t){ | ||
var ret = new t.transport(url); | ||
ret.heart = t.heart; | ||
return ret; | ||
} | ||
|
||
tn++; | ||
} | ||
|
||
c++; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
var stream = new function(){ | ||
var readyState = CLOSED; | ||
var heartbeat; | ||
var delay = delayDefault = 80; | ||
|
||
var transport = next(); | ||
function init(){ | ||
readyState = CONNECTING; | ||
|
||
if (!transport){ | ||
// No transport, give up | ||
// @todo Trigger a disconnect error | ||
return false; | ||
} | ||
|
||
transport.onopen = function(){ | ||
// We got a connection, reset the poll delay | ||
delay = delayDefault; | ||
|
||
if (transport.heart){ | ||
heartbeat = setInterval(function(){stream.onheartbeat();}, 20000); | ||
} | ||
|
||
if (readyState != OPEN){ | ||
readyState = OPEN; | ||
stream.onopen(); | ||
} | ||
}; | ||
transport.onclose = function(){ | ||
clearInterval(heartbeat); | ||
|
||
if (readyState == CLOSING){ | ||
readyState = CLOSED; | ||
stream.onclose(); | ||
} else{ | ||
// Close happened on connect, select next transport | ||
if (readyState == CONNECTING){ | ||
tn++; | ||
} | ||
|
||
delay *= 2; | ||
if (delay > 10000){ | ||
delay = 10000; | ||
} | ||
|
||
setTimeout(function(){ | ||
transport = next(); | ||
init(); | ||
}, delay); | ||
} | ||
}; | ||
transport.onerror = transport.onclose; | ||
transport.onmessage = function(e){ | ||
stream.onmessage(e); | ||
}; | ||
} | ||
init(); | ||
|
||
this.onopen = function(){}; | ||
this.onmessage = function(){}; | ||
this.onclose = function(){}; | ||
this.onheartbeat = function(){}; | ||
|
||
this.setURL = function(newURL){ | ||
url = newURL; | ||
}; | ||
this.send = function(data){ | ||
return transport.send(data); | ||
}; | ||
this.close = function(){ | ||
readyState = CLOSING; | ||
transport.close(); | ||
}; | ||
}; | ||
|
||
return stream; | ||
}})})(jQuery); |
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 |
---|---|---|
@@ -1,4 +1,5 @@ | ||
%%-*- mode: erlang -*- | ||
{deps, [ | ||
{cowboy, ".*", {git, "git://github.com/extend/cowboy.git", "master"}} | ||
{cowboy, ".*", {git, "git://github.com/extend/cowboy.git", "master"}}, | ||
{bullet, ".*", {git, "https://github.com/extend/bullet.git", "master"}} | ||
]}. |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
-module(stream_handler). | ||
-export([init/4, stream/3, info/3, terminate/2]). | ||
|
||
init(_Transport, Req, _Opts, Active) -> | ||
io:format("INIT. Active: ~p~n", [Active]), | ||
{ok, Req, undefined_state}. | ||
|
||
stream(Data, Req, State) -> | ||
io:format("STREAM. Data: ~p~n", [Data]), | ||
{reply, Data, Req, State}. | ||
|
||
info(_Info, Req, State) -> | ||
{ok, Req, State}. | ||
|
||
terminate(_Req, _State) -> | ||
io:format("TERMINATE.~n"), | ||
ok. |
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