mirror of
https://github.com/teampoltergeist/poltergeist.git
synced 2022-11-09 12:05:00 -05:00
Merge pull request #322 from jcoglan/websocket-driver
Replace faye-websocket with websocket-driver.
This commit is contained in:
commit
c2495eaf44
2 changed files with 15 additions and 79 deletions
|
@ -1,7 +1,5 @@
|
||||||
require 'socket'
|
require 'socket'
|
||||||
require 'stringio'
|
require 'websocket/driver'
|
||||||
require 'http/parser'
|
|
||||||
require 'faye/websocket'
|
|
||||||
|
|
||||||
module Capybara::Poltergeist
|
module Capybara::Poltergeist
|
||||||
# This is a 'custom' Web Socket server that is designed to be synchronous. What
|
# This is a 'custom' Web Socket server that is designed to be synchronous. What
|
||||||
|
@ -11,45 +9,6 @@ module Capybara::Poltergeist
|
||||||
# how Web Sockets are usually used, but it's what we want here, as we want to
|
# how Web Sockets are usually used, but it's what we want here, as we want to
|
||||||
# send a message to PhantomJS and then wait for it to respond).
|
# send a message to PhantomJS and then wait for it to respond).
|
||||||
class WebSocketServer
|
class WebSocketServer
|
||||||
class FayeHandler
|
|
||||||
attr_reader :owner, :env, :parser
|
|
||||||
|
|
||||||
def initialize(owner, env)
|
|
||||||
@owner = owner
|
|
||||||
@env = env
|
|
||||||
@parser = Faye::WebSocket.parser(env).new(self)
|
|
||||||
@messages = []
|
|
||||||
end
|
|
||||||
|
|
||||||
def url
|
|
||||||
"ws://#{env['SERVER_NAME']}:#{env['SERVER_PORT']}/"
|
|
||||||
end
|
|
||||||
|
|
||||||
def handshake_response
|
|
||||||
parser.handshake_response
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse(data)
|
|
||||||
parser.parse(data)
|
|
||||||
end
|
|
||||||
|
|
||||||
def encode(message)
|
|
||||||
parser.frame(Faye::WebSocket.encode(message))
|
|
||||||
end
|
|
||||||
|
|
||||||
def receive(message)
|
|
||||||
@messages << message
|
|
||||||
end
|
|
||||||
|
|
||||||
def message?
|
|
||||||
@messages.any?
|
|
||||||
end
|
|
||||||
|
|
||||||
def next_message
|
|
||||||
@messages.shift
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# How much to try to read from the socket at once (it's kinda arbitrary because we
|
# How much to try to read from the socket at once (it's kinda arbitrary because we
|
||||||
# just keep reading until we've received a full frame)
|
# just keep reading until we've received a full frame)
|
||||||
RECV_SIZE = 1024
|
RECV_SIZE = 1024
|
||||||
|
@ -59,12 +18,11 @@ module Capybara::Poltergeist
|
||||||
|
|
||||||
HOST = '127.0.0.1'
|
HOST = '127.0.0.1'
|
||||||
|
|
||||||
attr_reader :port, :parser, :socket, :handler, :server
|
attr_reader :port, :driver, :socket, :server
|
||||||
attr_accessor :timeout
|
attr_accessor :timeout
|
||||||
|
|
||||||
def initialize(port = nil, timeout = nil)
|
def initialize(port = nil, timeout = nil)
|
||||||
@timeout = timeout
|
@timeout = timeout
|
||||||
@parser = Http::Parser.new
|
|
||||||
@server = start_server(port)
|
@server = start_server(port)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -94,37 +52,16 @@ module Capybara::Poltergeist
|
||||||
# Accept a client on the TCP server socket, then receive its initial HTTP request
|
# Accept a client on the TCP server socket, then receive its initial HTTP request
|
||||||
# and use that to initialize a Web Socket.
|
# and use that to initialize a Web Socket.
|
||||||
def accept
|
def accept
|
||||||
@socket = server.accept
|
@socket = server.accept
|
||||||
|
@messages = []
|
||||||
|
|
||||||
while msg = socket.gets
|
@driver = ::WebSocket::Driver.server(self)
|
||||||
parser << msg
|
@driver.on(:connect) { |event| @driver.start }
|
||||||
break if msg == "\r\n"
|
@driver.on(:message) { |event| @messages << event.data }
|
||||||
end
|
|
||||||
|
|
||||||
@handler = FayeHandler.new(self, env)
|
|
||||||
socket.write handler.handshake_response
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Note that the socket.read(8) assumes we're using the hixie-76 parser. This is
|
def write(data)
|
||||||
# fine for now as it corresponds to the version of Web Sockets that the version of
|
@socket.write(data)
|
||||||
# WebKit in PhantomJS uses, but it might need to change in the future.
|
|
||||||
def env
|
|
||||||
@env ||= begin
|
|
||||||
env = {
|
|
||||||
'REQUEST_METHOD' => parser.http_method,
|
|
||||||
'SCRIPT_NAME' => '',
|
|
||||||
'PATH_INFO' => '',
|
|
||||||
'QUERY_STRING' => '',
|
|
||||||
'SERVER_NAME' => '127.0.0.1',
|
|
||||||
'SERVER_PORT' => port.to_s,
|
|
||||||
'HTTP_ORIGIN' => 'http://127.0.0.1:2000/',
|
|
||||||
'rack.input' => StringIO.new(socket.read(8))
|
|
||||||
}
|
|
||||||
parser.headers.each do |header, value|
|
|
||||||
env['HTTP_' + header.upcase.gsub('-', '_')] = value
|
|
||||||
end
|
|
||||||
env
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Block until the next message is available from the Web Socket.
|
# Block until the next message is available from the Web Socket.
|
||||||
|
@ -132,21 +69,21 @@ module Capybara::Poltergeist
|
||||||
def receive
|
def receive
|
||||||
start = Time.now
|
start = Time.now
|
||||||
|
|
||||||
until handler.message?
|
until @messages.any?
|
||||||
raise Errno::EWOULDBLOCK if (Time.now - start) >= timeout
|
raise Errno::EWOULDBLOCK if (Time.now - start) >= timeout
|
||||||
IO.select([socket], [], [], timeout) or raise Errno::EWOULDBLOCK
|
IO.select([socket], [], [], timeout) or raise Errno::EWOULDBLOCK
|
||||||
data = socket.recv(RECV_SIZE)
|
data = socket.recv(RECV_SIZE)
|
||||||
break if data.empty?
|
break if data.empty?
|
||||||
handler.parse(data)
|
driver.parse(data)
|
||||||
end
|
end
|
||||||
|
|
||||||
handler.next_message
|
@messages.shift
|
||||||
end
|
end
|
||||||
|
|
||||||
# Send a message and block until there is a response
|
# Send a message and block until there is a response
|
||||||
def send(message)
|
def send(message)
|
||||||
accept unless connected?
|
accept unless connected?
|
||||||
socket.write handler.encode(message)
|
driver.text(message)
|
||||||
receive
|
receive
|
||||||
rescue Errno::EWOULDBLOCK
|
rescue Errno::EWOULDBLOCK
|
||||||
raise TimeoutError.new(message)
|
raise TimeoutError.new(message)
|
||||||
|
|
|
@ -16,9 +16,8 @@ Gem::Specification.new do |s|
|
||||||
|
|
||||||
s.required_ruby_version = ">= 1.9.2"
|
s.required_ruby_version = ">= 1.9.2"
|
||||||
|
|
||||||
s.add_dependency "capybara", "~> 2.1.0"
|
s.add_dependency "capybara", "~> 2.1.0"
|
||||||
s.add_dependency "http_parser.rb", "~> 0.5.3"
|
s.add_dependency "websocket-driver", ">= 0.2.0"
|
||||||
s.add_dependency "faye-websocket", ">= 0.4.4", "< 0.5.0"
|
|
||||||
|
|
||||||
s.add_development_dependency 'rspec', '~> 2.12'
|
s.add_development_dependency 'rspec', '~> 2.12'
|
||||||
s.add_development_dependency 'sinatra', '~> 1.0'
|
s.add_development_dependency 'sinatra', '~> 1.0'
|
||||||
|
|
Loading…
Add table
Reference in a new issue