Skip to content

Instantly share code, notes, and snippets.

@hayajo
Last active August 29, 2015 14:06
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hayajo/54cbbc7331cd743aceb9 to your computer and use it in GitHub Desktop.
Save hayajo/54cbbc7331cd743aceb9 to your computer and use it in GitHub Desktop.
HerokuでWebsocket
.*
!.gitignore
*~
local/
log/
*.pid

HerokuでWebsocket

Usage

  • Production(on Heroku)

      $ heroku create APP_NAME --buildpack=https://github.com/kazeburo/heroku-buildpack-perl-procfile.git
      $ heroku addons:add redistogo:nano
      $ git push heroku master
    

    Access to http://APP_NAME.herokuapp.com/

  • Development(on localhost with docker)

      $ carton install
      $ docker run -d --name redis dockerfile/redis
      $ REDIS_HOST=$(docker inspect -f '{{.NetworkSettings.IPAddress}}' redis):6379 \
        MOJO_LOG_LEVEL=debug \
        carton exec -- proclet start
    

    Access to http://localhost:8080/

#!/usr/bin/env perl
use Mojolicious::Lite;
use Mojo::Util qw/hmac_sha1_sum xml_escape/;
use Mojo::JSON qw/decode_json encode_json/;
use Mojo::Redis2;
use Encode qw/decode_utf8 encode_utf8/;
app->config(
hypnotoad => {
listen => [ 'http://*:' . ( $ENV{PORT} || 8080 ) ],
},
);
get '/' => 'index';
websocket '/chat' => sub {
my $c = shift;
$c->inactivity_timeout(30);
$c->app->log->debug("websocket opened");
my $redis = Mojo::Redis2->new( url => $ENV{REDISTOGO_URL}
|| ( 'redis://' . $ENV{REDIS_HOST} || '127.0.0.1:6379' ) );
my $sub = $redis->subscribe('chan:chat');
$sub->on(
message => sub {
my ( $redis, $data, $chan ) = @_;
$c->send( { json => decode_json($data) } );
}
);
$c->on(
message => sub {
my ( $c, $msg ) = @_;
my $data = decode_json( encode_utf8($msg) );
if ( $data->{ping} ) {
$c->app->log->debug('ping received');
$c->send( { json => { pong => 1 } } );
$redis->publish( 'chan:chat:dummy' => 1 ); # to keep redis session
return;
}
$data->{time} = time;
$redis->publish( 'chan:chat' => encode_json($data) );
}
);
$c->on(
finish => sub {
my ( $c, $code, $reason ) = @_;
$c->app->log->debug("websocket closed with status $code");
delete $c->stash->{redis};
}
);
$c->stash( redis => $redis );
};
app->start;
__DATA__
@@ index.html.ep
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Simple Chat</title>
</head>
<body>
<div><input type="text" id="message"/></div>
<div id="log"></div>
<script>
var keepalive;
var ws = new WebSocket('<%= url_for('chat')->to_abs %>');
function log(date, msg) {
document.getElementById('log').innerHTML
+= '<p>' + date + ' ' + msg + '</p>';
}
ws.onmessage = function(e) {
var data = JSON.parse(e.data);
if (data.pong) {
console.log('receive pong');
return;
}
log(new Date(data.time * 1000), data.msg);
};
ws.onclose = function(e) {
clearInterval(keepalive);
ws = null;
log('', 'connection closed by forign host.');
};
keepalive = window.setInterval( function () {
var msg = JSON.stringify({ 'ping': true });
console.log('send ping');
ws.send(msg);
}, 15000); // sends a ping every 15 seconds
document.getElementById('message').onkeydown = function(e) {
if (e.keyCode == 13 && e.currentTarget.value != '') {
var msg = JSON.stringify({'msg': e.currentTarget.value});
ws.send(msg);
e.currentTarget.value = '';
}
};
</script>
</body>
</html>
requires "Mojolicious", "0";
requires "Mojo::Redis2", "0";
requires "Proclet", "0";
web: hypnotoad -f app.pl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment