I am trying to use the same port to serve regular HTTP traffic, as well as websocket HTML5 through Cramp (which is built on top of EventMachine) using Ruby 1.9.3 and Thin 1.3.1. Here is a minimal, self-sufficient example:
require 'thin'
require 'cramp'
require 'http_router'
Cramp::Websocket.backend = :thin
class SocketApp < Cramp::Action
self.transport = :websocket
on_start = :connected
on_finish = :disconnected
on_data = :message
def connected
puts 'Client connected'
end
def disconnected
puts 'Client disconnected'
end
def message(msg)
puts "Got message: #{msg}"
render 'Here is your reply'
end
end
class WebApp
def call(env)
[ 200, { 'Content-Type' => 'text/html' }, <<EOF
<html><head>
<script>
function init() {
function log(msg) { document.getElementById('log').innerHTML += msg + '<br>'; }
var socketUri = 'ws://' + document.location.host + '/socket';
log('Socket URI: ' + socketUri);
var socket = new WebSocket(socketUri);
socket.onopen = function(e) {
log('onopen');
socket.send('Is there anybody out there?');
log('sent message');
};
socket.onclose = function(e) {
log('onclose; code = ' + e.code + ', reason = ' + e.reason);
};
socket.onerror = function(e) {
log('onerror');
};
socket.onmessage = function(e) {
log('onmessage; data = ' + e.data);
};
}
</script>
</head><body onload='init();'>
<h1>Serving Cramp::Websocket and normal Rack app on the same port</h1>
<p id='log'></p>
</body></html>
EOF
]
end
end
app = HttpRouter.new do
add('/socket').to SocketApp
add('/').to WebApp.new
end
run app
If you want to try this for yourself, paste this code into a file with a name config.ruand run it thin start. You need gems thin, crampand http_routerfor installation.
, JavaScript WebSocket ws://localhost:3000/socket, , , . open , , .
, Client connected .
thin start -D, , HTTP 101 , .
?
. , HttpRouter thin , . , , HttpRouter WebApp.