Class: Capybara::Poltergeist::WebSocketServer
- Inherits:
-
Object
- Object
- Capybara::Poltergeist::WebSocketServer
- Defined in:
- lib/capybara/poltergeist/web_socket_server.rb
Overview
This is a ‘custom’ Web Socket server that is designed to be synchronous. What this means is that it sends a message, and then waits for a response. It does not expect to receive a message at any other time than right after it has sent a message. So it is basically operating a request/response cycle (which is not 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).
Defined Under Namespace
Classes: FayeHandler
Constant Summary collapse
- RECV_SIZE =
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)
1024
Instance Attribute Summary collapse
-
#handler ⇒ Object
readonly
Returns the value of attribute handler.
-
#parser ⇒ Object
readonly
Returns the value of attribute parser.
-
#port ⇒ Object
readonly
Returns the value of attribute port.
-
#server ⇒ Object
readonly
Returns the value of attribute server.
-
#socket ⇒ Object
readonly
Returns the value of attribute socket.
-
#timeout ⇒ Object
Returns the value of attribute timeout.
Instance Method Summary collapse
-
#accept ⇒ Object
Accept a client on the TCP server socket, then receive its initial HTTP request and use that to initialize a Web Socket.
- #close ⇒ Object
- #connected? ⇒ Boolean
-
#env ⇒ Object
Note that the socket.read(8) assumes we’re using the hixie-76 parser.
-
#initialize(port, timeout = nil) ⇒ WebSocketServer
constructor
A new instance of WebSocketServer.
-
#receive ⇒ Object
Block until the next message is available from the Web Socket.
-
#send(message) ⇒ Object
Send a message and block until there is a response.
Constructor Details
#initialize(port, timeout = nil) ⇒ WebSocketServer
Returns a new instance of WebSocketServer.
60 61 62 63 64 65 |
# File 'lib/capybara/poltergeist/web_socket_server.rb', line 60 def initialize(port, timeout = nil) @port = port @parser = Http::Parser.new @server = TCPServer.open(port) @timeout = timeout end |
Instance Attribute Details
#handler ⇒ Object (readonly)
Returns the value of attribute handler.
57 58 59 |
# File 'lib/capybara/poltergeist/web_socket_server.rb', line 57 def handler @handler end |
#parser ⇒ Object (readonly)
Returns the value of attribute parser.
57 58 59 |
# File 'lib/capybara/poltergeist/web_socket_server.rb', line 57 def parser @parser end |
#port ⇒ Object (readonly)
Returns the value of attribute port.
57 58 59 |
# File 'lib/capybara/poltergeist/web_socket_server.rb', line 57 def port @port end |
#server ⇒ Object (readonly)
Returns the value of attribute server.
57 58 59 |
# File 'lib/capybara/poltergeist/web_socket_server.rb', line 57 def server @server end |
#socket ⇒ Object (readonly)
Returns the value of attribute socket.
57 58 59 |
# File 'lib/capybara/poltergeist/web_socket_server.rb', line 57 def socket @socket end |
#timeout ⇒ Object
Returns the value of attribute timeout.
58 59 60 |
# File 'lib/capybara/poltergeist/web_socket_server.rb', line 58 def timeout @timeout end |
Instance Method Details
#accept ⇒ Object
Accept a client on the TCP server socket, then receive its initial HTTP request and use that to initialize a Web Socket.
73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/capybara/poltergeist/web_socket_server.rb', line 73 def accept @socket = server.accept while msg = socket.gets parser << msg break if msg == "\r\n" end @handler = FayeHandler.new(self, env) socket.write handler.handshake_response end |
#close ⇒ Object
128 129 130 131 132 133 |
# File 'lib/capybara/poltergeist/web_socket_server.rb', line 128 def close [server, socket].each do |s| s.close_read s.close_write end end |
#connected? ⇒ Boolean
67 68 69 |
# File 'lib/capybara/poltergeist/web_socket_server.rb', line 67 def connected? !socket.nil? end |
#env ⇒ Object
Note that the socket.read(8) assumes we’re using the hixie-76 parser. This is fine for now as it corresponds to the version of Web Sockets that the version of WebKit in PhantomJS uses, but it might need to change in the future.
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/capybara/poltergeist/web_socket_server.rb', line 88 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 |
#receive ⇒ Object
Block until the next message is available from the Web Socket
108 109 110 111 112 113 114 115 116 117 |
# File 'lib/capybara/poltergeist/web_socket_server.rb', line 108 def receive until handler. IO.select([socket], [], [], timeout) data = socket.recv_nonblock(RECV_SIZE) break if data.empty? handler.parse(data) end handler. end |
#send(message) ⇒ Object
Send a message and block until there is a response
120 121 122 123 124 125 126 |
# File 'lib/capybara/poltergeist/web_socket_server.rb', line 120 def send() accept unless connected? socket.write handler.encode() receive rescue Errno::EAGAIN, Errno::EWOULDBLOCK raise TimeoutError.new() end |