socketry / async-websocket

Asynchronous WebSocket client and server, supporting HTTP/1 and HTTP/2 for Ruby.
MIT License
173 stars 17 forks source link

How to check for upgrade request? #11

Closed destructobeam closed 5 years ago

destructobeam commented 5 years ago

In a previous version when writing Rack middleware you could use the following to check for an upgrade request:

if ::WebSocket::Driver.websocket?(env)
  middleware_code...
end

Is there an equivalent using protocol-websocket?

Also an alternative to the following would be cool to doc up?

case event
when ::WebSocket::Driver::OpenEvent
  ...do_something
when ::WebSocket::Driver::MessageEvent
  ...do_something
when ::WebSocket::Driver::CloseEvent
  ...do_something
end                                                              
ioquatix commented 5 years ago

Doing a check like websocket? isn't going to be efficient if the entire point is just to open a websocket connection. But there is no reason why we can't add it - but it also doesn't guarantee the connection will be established because there are things like a sec-websocket-accept which need to be validated.

On the 2nd point, OpenEvent isn't actually a real event, it's faked by the websocket driver code because it uses callbacks, so it means "I'm connected now". But in async-websocket, it's not necessary, just write your code inline with Rack.open do |connection|; ... open code here

Regarding message event, you can get messages from the connection object next_message. If it returns nil it means the connection was closed gracefully, if it raises a ClosedError it means the remote end closed the connection with an error (non-1001 close status code).

I'll think about writing some documentation to make this clear.

destructobeam commented 5 years ago

Thanks. Second point makes sense.

In regards to the first, I am running the websocket middleware on the same server that handles normal HTTP requests, so would assume I need to check that there is an upgrade requested before trying to establish a new socket, otherwise the middleware would be trying to upgrade all requests?

ioquatix commented 5 years ago

Nope, it's opportunistic, so if it can't upgrade the connection it returns nil.

Let me update the example.

ioquatix commented 5 years ago

There are a couple of bugs which prevent this from working correctly, so I'm updating the specs to cover all these cases.. you'll need to wait for the next release.

destructobeam commented 5 years ago

Thanks! Will rollback in the meantime.

ioquatix commented 5 years ago

Because this is highly "Rack" specific, I've added: Async::WebSocket::Server::Rack.websocket?(env).

All the rest is as explained and working in v0.10.0 which should be released shortly.

ioquatix commented 5 years ago

https://github.com/socketry/async-websocket#server-side-with-rack--falcon shows how to do the opportunistic request/fallback to @app.call