websocket-rack 0.1.4 → 0.2.1

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.
Files changed (40) hide show
  1. data/CHANGELOG.md +11 -0
  2. data/README.md +42 -24
  3. data/Rakefile +1 -1
  4. data/example/example.ru +5 -5
  5. data/lib/rack/websocket/application.rb +31 -60
  6. data/lib/rack/websocket/extensions/common.rb +61 -0
  7. data/lib/rack/websocket/extensions/thin/connection.rb +2 -50
  8. data/lib/rack/websocket/extensions/thin.rb +3 -3
  9. data/lib/rack/websocket/extensions.rb +14 -0
  10. data/lib/rack/websocket/handler/base.rb +41 -0
  11. data/lib/rack/websocket/handler/stub.rb +14 -0
  12. data/lib/rack/websocket/handler/thin/connection.rb +89 -0
  13. data/lib/rack/websocket/handler/thin/handler_factory.rb +56 -0
  14. data/lib/rack/websocket/handler/thin.rb +61 -0
  15. data/lib/rack/websocket/handler.rb +15 -38
  16. data/lib/rack/websocket/version.rb +5 -0
  17. data/lib/rack/websocket.rb +5 -31
  18. data/spec/spec_helper.rb +18 -0
  19. data/spec/support/all_drafts.rb +43 -0
  20. data/spec/support/all_handlers.rb +31 -0
  21. data/spec/support/requests.rb +100 -0
  22. data/spec/thin_spec.rb +46 -0
  23. data/websocket-rack.gemspec +4 -4
  24. metadata +41 -47
  25. data/lib/rack/websocket/connection.rb +0 -112
  26. data/lib/rack/websocket/debugger.rb +0 -17
  27. data/lib/rack/websocket/framing03.rb +0 -178
  28. data/lib/rack/websocket/framing76.rb +0 -115
  29. data/lib/rack/websocket/handler03.rb +0 -14
  30. data/lib/rack/websocket/handler75.rb +0 -8
  31. data/lib/rack/websocket/handler76.rb +0 -11
  32. data/lib/rack/websocket/handler_factory.rb +0 -61
  33. data/lib/rack/websocket/handshake75.rb +0 -21
  34. data/lib/rack/websocket/handshake76.rb +0 -71
  35. data/spec/helper.rb +0 -44
  36. data/spec/integration/draft03_spec.rb +0 -252
  37. data/spec/integration/draft76_spec.rb +0 -212
  38. data/spec/unit/framing_spec.rb +0 -108
  39. data/spec/unit/handler_spec.rb +0 -136
  40. data/spec/websocket_spec.rb +0 -210
@@ -0,0 +1,61 @@
1
+ require 'thin'
2
+
3
+ module Rack
4
+ module WebSocket
5
+ module Handler
6
+ class Thin < Base
7
+
8
+ autoload :Connection, "#{ROOT_PATH}/websocket/handler/thin/connection"
9
+ autoload :HandlerFactory, "#{ROOT_PATH}/websocket/handler/thin/handler_factory"
10
+
11
+ def call(env)
12
+ @env = env
13
+ socket = env['async.connection']
14
+ request = request_from_env(env)
15
+ @conn = Connection.new(self, socket, :debug => @options[:debug])
16
+ @conn.dispatch(request) ? async_response : failure_response
17
+ end
18
+
19
+ def send_data(data)
20
+ if @conn
21
+ @conn.send data
22
+ else
23
+ raise WebSocketError, "WebSocket not opened"
24
+ end
25
+ end
26
+
27
+ def close_websocket
28
+ if @conn
29
+ @conn.close_websocket
30
+ else
31
+ raise WebSocketError, "WebSocket not opened"
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def request_from_env(env)
38
+ request = {}
39
+ request['Path'] = env['REQUEST_PATH'].to_s
40
+ request['Method'] = env['REQUEST_METHOD']
41
+ request['Query'] = env['QUERY_STRING'].to_s
42
+ request['body'] = env['rack.input'].read
43
+
44
+ request['Sec-WebSocket-Draft'] = env['HTTP_SEC_WEBSOCKET_DRAFT']
45
+ request['Sec-WebSocket-Key1'] = env['HTTP_SEC_WEBSOCKET_KEY1']
46
+ request['Sec-WebSocket-Key2'] = env['HTTP_SEC_WEBSOCKET_KEY2']
47
+ request['Sec-WebSocket-Protocol'] = env['HTTP_SEC_WEBSOCKET_PROTOCOL']
48
+
49
+ env.each do |key, value|
50
+ if key.match(/HTTP_(.+)/)
51
+ request[$1.capitalize.gsub('_','-')] ||= value
52
+ end
53
+ end
54
+
55
+ request
56
+ end
57
+
58
+ end
59
+ end
60
+ end
61
+ end
@@ -1,43 +1,20 @@
1
1
  module Rack
2
2
  module WebSocket
3
- class Handler
4
- include Debugger
5
-
6
- attr_reader :request, :state
7
-
8
- def initialize(connection, request, debug = false)
9
- @connection, @request = connection, request
10
- @debug = debug
11
- @state = :handshake
12
- initialize_framing
13
- end
14
-
15
- def run
16
- @connection.send_data handshake
17
- @state = :connected
18
- @connection.trigger_on_open
19
- end
20
-
21
- # Handshake response
22
- def handshake
23
- # Implemented in subclass
24
- end
25
-
26
- def receive_data(data)
27
- @data << data
28
- process_data(data)
29
- end
30
-
31
- def close_websocket
32
- # Unless redefined in a subclass, just close the connection
33
- @state = :closed
34
- @connection.close_connection_after_writing
35
- end
36
-
37
- def unbind
38
- @state = :closed
39
- @connection.trigger_on_close
3
+ module Handler
4
+
5
+ autoload :Base, "#{ROOT_PATH}/websocket/handler/base"
6
+ autoload :Stub, "#{ROOT_PATH}/websocket/handler/stub"
7
+ autoload :Thin, "#{ROOT_PATH}/websocket/handler/thin"
8
+
9
+ def self.detect(env)
10
+ server_software = env['SERVER_SOFTWARE']
11
+ if server_software.match(/\Athin /i)
12
+ Thin
13
+ else
14
+ Stub
15
+ end
40
16
  end
17
+
41
18
  end
42
19
  end
43
- end
20
+ end
@@ -0,0 +1,5 @@
1
+ module Rack
2
+ module WebSocket
3
+ VERSION = "0.2.1"
4
+ end
5
+ end
@@ -1,40 +1,14 @@
1
1
  require 'rack'
2
+ require 'em-websocket'
2
3
 
3
4
  module Rack
4
5
  module WebSocket
5
- VERSION = "0.1.4"
6
6
  ROOT_PATH = ::File.expand_path(::File.dirname(__FILE__))
7
7
 
8
- class WebSocketError < RuntimeError; end
9
- class HandshakeError < WebSocketError; end
10
- class DataError < WebSocketError; end
11
-
12
- autoload :Application, "#{ROOT_PATH}/websocket/application"
13
- autoload :Connection, "#{ROOT_PATH}/websocket/connection"
14
- autoload :Debugger, "#{ROOT_PATH}/websocket/debugger"
15
- autoload :Framing03, "#{ROOT_PATH}/websocket/framing03"
16
- autoload :Framing76, "#{ROOT_PATH}/websocket/framing76"
17
- autoload :Handler, "#{ROOT_PATH}/websocket/handler"
18
- autoload :Handler03, "#{ROOT_PATH}/websocket/handler03"
19
- autoload :Handler75, "#{ROOT_PATH}/websocket/handler75"
20
- autoload :Handler76, "#{ROOT_PATH}/websocket/handler76"
21
- autoload :HandlerFactory, "#{ROOT_PATH}/websocket/handler_factory"
22
- autoload :Handshake75, "#{ROOT_PATH}/websocket/handshake75"
23
- autoload :Handshake76, "#{ROOT_PATH}/websocket/handshake76"
24
-
25
- module Extensions
26
- autoload :Thin, "#{ROOT_PATH}/websocket/extensions/thin"
27
- end
28
-
8
+ autoload :Application, "#{ROOT_PATH}/websocket/application"
9
+ autoload :Extensions, "#{ROOT_PATH}/websocket/extensions"
10
+ autoload :Handler, "#{ROOT_PATH}/websocket/handler"
29
11
  end
30
12
  end
31
13
 
32
- ::Thin.send(:include, ::Rack::WebSocket::Extensions::Thin) if defined?(Thin)
33
-
34
- unless ''.respond_to?(:getbyte)
35
- class String
36
- def getbyte(i)
37
- self[i]
38
- end
39
- end
40
- end
14
+ Rack::WebSocket::Extensions.apply!
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'rspec'
3
+
4
+ require 'rack/websocket'
5
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
6
+
7
+ RSpec.configure do |config|
8
+ config.mock_with :mocha
9
+ end
10
+
11
+ class TestApp < Rack::WebSocket::Application
12
+ end
13
+
14
+ TEST_PORT = 8081
15
+
16
+ def new_server_connection
17
+ TCPSocket.new('localhost', TEST_PORT)
18
+ end
@@ -0,0 +1,43 @@
1
+ shared_examples_for 'all drafts' do
2
+ it "should accept incoming connection" do
3
+ conn = new_server_connection
4
+ conn.write(handshake_request)
5
+ conn.read(handshake_response.length).should eql(handshake_response)
6
+ end
7
+ it "should call 'on_open' on new connection" do
8
+ TestApp.any_instance.expects(:on_open)
9
+ conn = new_server_connection
10
+ conn.write(handshake_request)
11
+ end
12
+ it "should call 'on_open' on new connection with proper env" do
13
+ TestApp.any_instance.expects(:on_open).once.with { |env| env.class == Hash && !env.keys.empty? }
14
+ conn = new_server_connection
15
+ conn.write(handshake_request)
16
+ end
17
+ it "should call 'on_close' on connection close" do
18
+ TestApp.any_instance.expects(:on_close)
19
+ conn = new_server_connection
20
+ conn.write(handshake_request)
21
+ conn.close
22
+ end
23
+ it "should call 'on_close' on connection close with proper env" do
24
+ TestApp.any_instance.expects(:on_close).once.with { |env| env.class == Hash && !env.keys.empty? }
25
+ conn = new_server_connection
26
+ conn.write(handshake_request)
27
+ conn.close
28
+ end
29
+ it "should call 'on_message' on connection sending data" do
30
+ TestApp.any_instance.expects(:on_message)
31
+ conn = new_server_connection
32
+ conn.write(handshake_request)
33
+ conn.read(handshake_response.length)
34
+ conn.write(message)
35
+ end
36
+ it "should call 'on_message' on connection sending data with proper env and message" do
37
+ TestApp.any_instance.expects(:on_message).once.with { |env, message| env.class == Hash && !env.keys.empty? && message == 'some message' }
38
+ conn = new_server_connection
39
+ conn.write(handshake_request)
40
+ conn.read(handshake_response.length)
41
+ conn.write(message)
42
+ end
43
+ end
@@ -0,0 +1,31 @@
1
+ shared_examples_for 'all handlers' do
2
+ it "should return flash policy file" do
3
+ conn = new_server_connection
4
+ conn.write(flash_policy_request)
5
+ conn.read(flash_policy_response.length).should eql(flash_policy_response)
6
+ end
7
+
8
+ context 'for draft75' do
9
+ let(:handshake_request) { spec75_handshake_request }
10
+ let(:handshake_response) { spec75_handshake_response }
11
+ let(:message) { spec75_message }
12
+
13
+ it_should_behave_like 'all drafts'
14
+ end
15
+
16
+ context 'for draft76' do
17
+ let(:handshake_request) { spec76_handshake_request }
18
+ let(:handshake_response) { spec76_handshake_response }
19
+ let(:message) { spec76_message }
20
+
21
+ it_should_behave_like 'all drafts'
22
+ end
23
+
24
+ context 'for draft03' do
25
+ let(:handshake_request) { spec03_handshake_request }
26
+ let(:handshake_response) { spec03_handshake_response }
27
+ let(:message) { spec03_message }
28
+
29
+ it_should_behave_like 'all drafts'
30
+ end
31
+ end
@@ -0,0 +1,100 @@
1
+ def flash_policy_request
2
+ "<policy-file-request/>\000"
3
+ end
4
+
5
+ def flash_policy_response
6
+ '<?xml version="1.0"?><cross-domain-policy><allow-access-from domain="*" to-ports="*"/></cross-domain-policy>'
7
+ end
8
+
9
+ def spec75_handshake_request
10
+ <<-EOF
11
+ GET / HTTP/1.1\r
12
+ Upgrade: WebSocket\r
13
+ Connection: Upgrade\r
14
+ Host: localhost:#{TEST_PORT}\r
15
+ Origin: http://localhost:#{TEST_PORT}\r
16
+ \r
17
+ EOF
18
+ end
19
+
20
+ def spec75_handshake_response
21
+ <<-EOF
22
+ HTTP/1.1 101 Web Socket Protocol Handshake\r
23
+ Upgrade: WebSocket\r
24
+ Connection: Upgrade\r
25
+ WebSocket-Origin: http://localhost:#{TEST_PORT}\r
26
+ WebSocket-Location: ws://localhost:#{TEST_PORT}/\r
27
+ \r
28
+ EOF
29
+ end
30
+
31
+ def spec75_message
32
+ "\x00some message\xff"
33
+ end
34
+
35
+ def spec76_handshake_request
36
+ request = <<-EOF
37
+ GET / HTTP/1.1\r
38
+ Upgrade: WebSocket\r
39
+ Connection: Upgrade\r
40
+ Host: localhost:#{TEST_PORT}\r
41
+ Origin: http://localhost:#{TEST_PORT}\r
42
+ Sec-WebSocket-Key1: 18x 6]8vM;54 *(5: { U1]8 z [ 8\r
43
+ Sec-WebSocket-Key2: 1_ tx7X d < nw 334J702) 7]o}` 0\r
44
+ \r
45
+ Tm[K T2u
46
+ EOF
47
+ request.rstrip
48
+ end
49
+
50
+ def spec76_handshake_response
51
+ response = <<-EOF
52
+ HTTP/1.1 101 WebSocket Protocol Handshake\r
53
+ Upgrade: WebSocket\r
54
+ Connection: Upgrade\r
55
+ Sec-WebSocket-Location: ws://localhost:#{TEST_PORT}/\r
56
+ Sec-WebSocket-Origin: http://localhost:#{TEST_PORT}\r
57
+ \r
58
+ fQJ,fN/4F4!~K~MH
59
+ EOF
60
+ response.rstrip
61
+ end
62
+
63
+ def spec76_message
64
+ "\x00some message\xff"
65
+ end
66
+
67
+ def spec03_handshake_request
68
+ request = <<-EOF
69
+ GET / HTTP/1.1\r
70
+ Upgrade: WebSocket\r
71
+ Connection: Upgrade\r
72
+ Host: localhost:#{TEST_PORT}\r
73
+ Origin: http://localhost:#{TEST_PORT}\r
74
+ Sec-WebSocket-Key1: 18x 6]8vM;54 *(5: { U1]8 z [ 8\r
75
+ Sec-WebSocket-Key2: 1_ tx7X d < nw 334J702) 7]o}` 0\r
76
+ Sec-WebSocket-Protocol: sample\r
77
+ Sec-WebSocket-Draft: 3\r
78
+ \r
79
+ Tm[K T2u
80
+ EOF
81
+ request.rstrip
82
+ end
83
+
84
+ def spec03_handshake_response
85
+ response = <<-EOF
86
+ HTTP/1.1 101 WebSocket Protocol Handshake\r
87
+ Upgrade: WebSocket\r
88
+ Connection: Upgrade\r
89
+ Sec-WebSocket-Location: ws://localhost:#{TEST_PORT}/\r
90
+ Sec-WebSocket-Origin: http://localhost:#{TEST_PORT}\r
91
+ Sec-WebSocket-Protocol: sample\r
92
+ \r
93
+ fQJ,fN/4F4!~K~MH
94
+ EOF
95
+ response.rstrip
96
+ end
97
+
98
+ def spec03_message
99
+ "\x04\x0Csome message"
100
+ end
data/spec/thin_spec.rb ADDED
@@ -0,0 +1,46 @@
1
+ require 'thin'
2
+ require 'spec_helper'
3
+
4
+ describe 'Thin handler' do
5
+ let(:app) { TestApp.new }
6
+
7
+ before(:all) { silent_thin }
8
+ before { start_thin_server(app) }
9
+ after { stop_thin_server }
10
+
11
+ it "should include extensions" do
12
+ ::Thin::Connection.include?(::Rack::WebSocket::Extensions::Common).should be_true
13
+ ::Thin::Connection.include?(::Rack::WebSocket::Extensions::Thin::Connection).should be_true
14
+ end
15
+
16
+ it_should_behave_like 'all handlers'
17
+ end
18
+
19
+ def start_thin_server(app, options = {})
20
+ @server = Thin::Server.new('0.0.0.0', TEST_PORT, options, app)
21
+ @server.ssl = options[:ssl]
22
+ # @server.threaded = options[:threaded]
23
+ # @server.timeout = 3
24
+
25
+ @thread = Thread.new { @server.start }
26
+ sleep 1 until @server.running?
27
+ end
28
+
29
+ def stop_thin_server
30
+ sleep 0.1
31
+ @server.stop!
32
+ @thread.kill
33
+ raise "Reactor still running, wtf?" if EventMachine.reactor_running?
34
+ end
35
+
36
+ def silent_thin
37
+ ::Thin::Logging.silent = true
38
+ if EM::VERSION < "1.0.0"
39
+ begin
40
+ old_verbose, $VERBOSE = $VERBOSE, nil
41
+ ::Thin::Server.const_set 'DEFAULT_TIMEOUT', 0
42
+ ensure
43
+ $VERBOSE = old_verbose
44
+ end
45
+ end
46
+ end
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  $:.push File.expand_path("../lib", __FILE__)
3
- require "rack/websocket"
3
+ require "rack/websocket/version"
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "websocket-rack"
@@ -13,10 +13,10 @@ Gem::Specification.new do |s|
13
13
  s.description = %q{Rack-based WebSocket server}
14
14
 
15
15
  s.add_dependency 'rack'
16
- s.add_dependency 'addressable', '>= 2.1.1'
17
- s.add_dependency 'eventmachine', '>= 0.12.9'
18
- s.add_dependency 'thin'
16
+ s.add_dependency 'em-websocket', '~> 0.2.1'
17
+ s.add_dependency 'thin' # Temporary until we support more servers
19
18
  s.add_development_dependency 'rspec', '~> 2.4.0'
19
+ s.add_development_dependency 'mocha'
20
20
 
21
21
  s.files = `git ls-files`.split("\n")
22
22
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: websocket-rack
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 21
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
+ - 2
8
9
  - 1
9
- - 4
10
- version: 0.1.4
10
+ version: 0.2.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Bernard Potocki
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-03-13 00:00:00 +01:00
18
+ date: 2011-04-01 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -33,65 +33,63 @@ dependencies:
33
33
  type: :runtime
34
34
  version_requirements: *id001
35
35
  - !ruby/object:Gem::Dependency
36
- name: addressable
36
+ name: em-websocket
37
37
  prerelease: false
38
38
  requirement: &id002 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
- - - ">="
41
+ - - ~>
42
42
  - !ruby/object:Gem::Version
43
- hash: 9
43
+ hash: 21
44
44
  segments:
45
+ - 0
45
46
  - 2
46
47
  - 1
47
- - 1
48
- version: 2.1.1
48
+ version: 0.2.1
49
49
  type: :runtime
50
50
  version_requirements: *id002
51
51
  - !ruby/object:Gem::Dependency
52
- name: eventmachine
52
+ name: thin
53
53
  prerelease: false
54
54
  requirement: &id003 !ruby/object:Gem::Requirement
55
55
  none: false
56
56
  requirements:
57
57
  - - ">="
58
58
  - !ruby/object:Gem::Version
59
- hash: 61
59
+ hash: 3
60
60
  segments:
61
61
  - 0
62
- - 12
63
- - 9
64
- version: 0.12.9
62
+ version: "0"
65
63
  type: :runtime
66
64
  version_requirements: *id003
67
65
  - !ruby/object:Gem::Dependency
68
- name: thin
66
+ name: rspec
69
67
  prerelease: false
70
68
  requirement: &id004 !ruby/object:Gem::Requirement
71
69
  none: false
72
70
  requirements:
73
- - - ">="
71
+ - - ~>
74
72
  - !ruby/object:Gem::Version
75
- hash: 3
73
+ hash: 31
76
74
  segments:
75
+ - 2
76
+ - 4
77
77
  - 0
78
- version: "0"
79
- type: :runtime
78
+ version: 2.4.0
79
+ type: :development
80
80
  version_requirements: *id004
81
81
  - !ruby/object:Gem::Dependency
82
- name: rspec
82
+ name: mocha
83
83
  prerelease: false
84
84
  requirement: &id005 !ruby/object:Gem::Requirement
85
85
  none: false
86
86
  requirements:
87
- - - ~>
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
- hash: 31
89
+ hash: 3
90
90
  segments:
91
- - 2
92
- - 4
93
91
  - 0
94
- version: 2.4.0
92
+ version: "0"
95
93
  type: :development
96
94
  version_requirements: *id005
97
95
  description: Rack-based WebSocket server
@@ -118,25 +116,22 @@ files:
118
116
  - example/html/web_socket.js
119
117
  - lib/rack/websocket.rb
120
118
  - lib/rack/websocket/application.rb
121
- - lib/rack/websocket/connection.rb
122
- - lib/rack/websocket/debugger.rb
119
+ - lib/rack/websocket/extensions.rb
120
+ - lib/rack/websocket/extensions/common.rb
123
121
  - lib/rack/websocket/extensions/thin.rb
124
122
  - lib/rack/websocket/extensions/thin/connection.rb
125
- - lib/rack/websocket/framing03.rb
126
- - lib/rack/websocket/framing76.rb
127
123
  - lib/rack/websocket/handler.rb
128
- - lib/rack/websocket/handler03.rb
129
- - lib/rack/websocket/handler75.rb
130
- - lib/rack/websocket/handler76.rb
131
- - lib/rack/websocket/handler_factory.rb
132
- - lib/rack/websocket/handshake75.rb
133
- - lib/rack/websocket/handshake76.rb
134
- - spec/helper.rb
135
- - spec/integration/draft03_spec.rb
136
- - spec/integration/draft76_spec.rb
137
- - spec/unit/framing_spec.rb
138
- - spec/unit/handler_spec.rb
139
- - spec/websocket_spec.rb
124
+ - lib/rack/websocket/handler/base.rb
125
+ - lib/rack/websocket/handler/stub.rb
126
+ - lib/rack/websocket/handler/thin.rb
127
+ - lib/rack/websocket/handler/thin/connection.rb
128
+ - lib/rack/websocket/handler/thin/handler_factory.rb
129
+ - lib/rack/websocket/version.rb
130
+ - spec/spec_helper.rb
131
+ - spec/support/all_drafts.rb
132
+ - spec/support/all_handlers.rb
133
+ - spec/support/requests.rb
134
+ - spec/thin_spec.rb
140
135
  - websocket-rack.gemspec
141
136
  has_rdoc: true
142
137
  homepage: http://github.com/imanel/websocket-rack
@@ -173,9 +168,8 @@ signing_key:
173
168
  specification_version: 3
174
169
  summary: Rack-based WebSocket server
175
170
  test_files:
176
- - spec/helper.rb
177
- - spec/integration/draft03_spec.rb
178
- - spec/integration/draft76_spec.rb
179
- - spec/unit/framing_spec.rb
180
- - spec/unit/handler_spec.rb
181
- - spec/websocket_spec.rb
171
+ - spec/spec_helper.rb
172
+ - spec/support/all_drafts.rb
173
+ - spec/support/all_handlers.rb
174
+ - spec/support/requests.rb
175
+ - spec/thin_spec.rb