em-websocket 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +1 -0
- data/VERSION +1 -1
- data/examples/echo.rb +1 -1
- data/lib/em-websocket/connection.rb +58 -13
- data/spec/websocket_spec.rb +1 -3
- metadata +2 -2
data/README.rdoc
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.2
|
data/examples/echo.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'lib/em-websocket'
|
2
2
|
|
3
|
-
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8080) do |ws|
|
3
|
+
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8080, :debug => true) do |ws|
|
4
4
|
ws.onopen { ws.send "Hello Client!"}
|
5
5
|
ws.onmessage { |msg| ws.send "Pong: #{msg}" }
|
6
6
|
ws.onclose { puts "WebSocket closed" }
|
@@ -1,7 +1,12 @@
|
|
1
|
+
require 'addressable/uri'
|
2
|
+
require 'uri'
|
1
3
|
module EventMachine
|
2
4
|
module WebSocket
|
3
5
|
class Connection < EventMachine::Connection
|
4
6
|
|
7
|
+
PATH = /^GET (\/[^\s]*) HTTP\/1\.1$/
|
8
|
+
HEADER = /^([^:]+):\s*([^$]+)/
|
9
|
+
|
5
10
|
# define WebSocket callbacks
|
6
11
|
def onopen(&blk); @onopen = blk; end
|
7
12
|
def onclose(&blk); @onclode = blk; end
|
@@ -11,14 +16,17 @@ module EventMachine
|
|
11
16
|
@options = options
|
12
17
|
@debug = options[:debug] || false
|
13
18
|
@state = :handshake
|
19
|
+
@request = {}
|
20
|
+
@data = ''
|
14
21
|
|
15
22
|
debug [:initialize]
|
16
23
|
end
|
17
24
|
|
18
25
|
def receive_data(data)
|
19
26
|
debug [:receive_data, data]
|
20
|
-
|
21
|
-
|
27
|
+
|
28
|
+
@data << data
|
29
|
+
dispatch
|
22
30
|
end
|
23
31
|
|
24
32
|
def unbind
|
@@ -26,33 +34,69 @@ module EventMachine
|
|
26
34
|
@onclose.call if @onclose
|
27
35
|
end
|
28
36
|
|
29
|
-
def dispatch
|
37
|
+
def dispatch
|
30
38
|
while case @state
|
31
39
|
when :handshake
|
32
|
-
new_request
|
40
|
+
new_request
|
33
41
|
when :upgrade
|
34
42
|
send_upgrade
|
35
43
|
when :connected
|
36
|
-
process_message
|
44
|
+
process_message
|
37
45
|
else raise RuntimeError, "invalid state: #{@state}"
|
38
46
|
end
|
39
47
|
end
|
40
48
|
end
|
41
49
|
|
42
|
-
def new_request
|
43
|
-
|
44
|
-
|
50
|
+
def new_request
|
51
|
+
if @data.match(/\r\n\r\n$/)
|
52
|
+
debug [:inbound_headers, @data]
|
53
|
+
lines = @data.split("\r\n")
|
54
|
+
|
55
|
+
# extract request path
|
56
|
+
@request['Path'] = lines.shift.match(PATH)[1].strip
|
57
|
+
|
58
|
+
# extract remaining headers
|
59
|
+
lines.each do |line|
|
60
|
+
h = HEADER.match(line)
|
61
|
+
@request[h[1].strip] = h[2].strip
|
62
|
+
end
|
63
|
+
|
64
|
+
# transform headers
|
65
|
+
@request['Host'] = Addressable::URI.parse("ws://"+@request['Host'])
|
66
|
+
|
67
|
+
if not websocket_connection?
|
68
|
+
send_data "HTTP/1.1 400 Bad request\r\n\r\n"
|
69
|
+
close_connection_after_writing
|
70
|
+
return false
|
71
|
+
|
72
|
+
else
|
73
|
+
@data = ''
|
74
|
+
@state = :upgrade
|
75
|
+
return true
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
false
|
80
|
+
end
|
81
|
+
|
82
|
+
def websocket_connection?
|
83
|
+
@request['Connection'] == 'Upgrade' and @request['Upgrade'] == 'WebSocket'
|
45
84
|
end
|
46
85
|
|
47
86
|
def send_upgrade
|
87
|
+
location = "ws://#{@request['Host'].host}"
|
88
|
+
location << ":#{@request['Host'].port}" if @request['Host'].port
|
89
|
+
location << @request['Path']
|
90
|
+
|
48
91
|
upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
|
49
92
|
upgrade << "Upgrade: WebSocket\r\n"
|
50
93
|
upgrade << "Connection: Upgrade\r\n"
|
51
|
-
upgrade << "WebSocket-Origin:
|
52
|
-
upgrade << "WebSocket-Location:
|
94
|
+
upgrade << "WebSocket-Origin: #{@request['Origin']}\r\n"
|
95
|
+
upgrade << "WebSocket-Location: #{location}\r\n\r\n"
|
53
96
|
|
54
97
|
# upgrade connection and notify client callback
|
55
98
|
# about completed handshake
|
99
|
+
debug [:upgrade_headers, upgrade]
|
56
100
|
send_data upgrade
|
57
101
|
|
58
102
|
@state = :connected
|
@@ -62,9 +106,10 @@ module EventMachine
|
|
62
106
|
false
|
63
107
|
end
|
64
108
|
|
65
|
-
def process_message
|
66
|
-
debug [:message, data]
|
67
|
-
@onmessage.call(data) if @onmessage
|
109
|
+
def process_message
|
110
|
+
debug [:message, @data]
|
111
|
+
@onmessage.call(@data) if @onmessage
|
112
|
+
@data = ''
|
68
113
|
|
69
114
|
false
|
70
115
|
end
|
data/spec/websocket_spec.rb
CHANGED
@@ -33,8 +33,6 @@ describe EventMachine::WebSocket do
|
|
33
33
|
end
|
34
34
|
|
35
35
|
it "should fail on non WebSocket requests" do
|
36
|
-
pending
|
37
|
-
|
38
36
|
EM.run do
|
39
37
|
EventMachine.add_timer(0.1) do
|
40
38
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :timeout => 0
|
@@ -45,7 +43,7 @@ describe EventMachine::WebSocket do
|
|
45
43
|
}
|
46
44
|
end
|
47
45
|
|
48
|
-
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8080
|
46
|
+
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8080) {}
|
49
47
|
end
|
50
48
|
end
|
51
49
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: em-websocket
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ilya Grigorik
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-12-
|
12
|
+
date: 2009-12-23 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|