我正在编写一个Sinatra web服务器,希望它是RESTful的,但问题在于它必须与另一个通过web sockets通信的服务器进行交互。因此,需要进行以下操作:
问题在于,它仍然无法正常工作。控制台输出如预期所示:
- 从客户端发送请求到我的Sinatra服务器
- 我的服务器打开一个到另一个服务器的web socket
- 我的服务器异步等待来自另一个服务器的消息和数据,直到socket关闭(这应该只需要约200毫秒)
- 我的服务器将响应发送回客户端
require 'sinatra'
require 'websocket-client-simple'
get '/' do
ws = WebSocket::Client::Simple.connect(' ws://URL... ')
ws.on :message do
puts 'bar'
end
ws.on :close do
# At this point we need to send an HTTP response back to the client. But how?
end
ws.on :open do
ws.send 'foo'
end
end
编辑
经过进一步思考,我意识到可以使用线程暂停和线程唤醒的方式来实现。这种方法可能有些复杂,而且我不确定如何在 Ruby 中正确地实现它,但基本思路如下:
require 'sinatra'
require 'websocket-client-simple'
get '/' do
socketResponse('wss:// ... URL ...')
'Got a response from the web socket server!'
end
def socketResponse(url)
thread = Thread.new do
ws = WebSocket::Client::Simple.connect(url)
ws.on :message do
puts 'bar'
# Maybe store each response in a thread-safe array to retrieve later or something
end
ws.on :close do
thread.run
end
ws.on :open do
ws.send 'foo'
end
Thread.stop
end
end
编辑2
我已经取得进一步的进展。我现在正在使用Async Sinatra宝石,这需要Thin Web服务器。以下是设置方法:
require 'sinatra'
require 'sinatra/async'
require 'websocket-client-simple'
set :server, 'thin'
register Sinatra::Async
aget '/' do
puts 'Request received'
socketResponse('wss:// ... URL ...')
end
def socketResponse(url)
ws = WebSocket::Client::Simple.connect(url)
puts 'Connected to web socket'
ws.on :message do |message|
puts 'Got message:' + message.to_s
end
ws.on :close do
puts 'WS closed'
body 'Closed ...'
end
ws.on :open do
puts 'WS open'
message = 'A nice message to process'
ws.send message
puts 'Sent: ' + message
end
end
问题在于,它仍然无法正常工作。控制台输出如预期所示:
Request received
Connected to web socket
WS open
Sent: A nice message to process
Got message: blah blah blah
WS closed
但是它没有向客户端发送任何数据。 body 'Closed ...'
方法似乎没有任何效果。
socketResponse()
应该阻塞直到WS关闭。这就是问题所在。 - tschwab