Skip to content
This repository has been archived by the owner on Dec 7, 2018. It is now read-only.

WebSockets support #4

Open
tarcieri opened this issue Sep 15, 2013 · 5 comments
Open

WebSockets support #4

tarcieri opened this issue Sep 15, 2013 · 5 comments

Comments

@tarcieri
Copy link
Member

The previous Rack adapter for Reel supported WebSockets through the reel.websocket environment variable.

Should reel-rack support WebSockets? Is a Rack environment variable the way to go? Or should there be a more direct API, possibly one that can bypass all of Rack's abstraction layers and just hand your program a WebSocket independently of Rack?

I think it'd be neat if reel-rack had a more direct WebSockets API. Maybe we can figure out one that becomes a standard for all Rack web servers support.

@collin
Copy link

collin commented Mar 17, 2014

I'm interested in the answer to this question.

I feel like it's nice if the API could hook into the middleware stack. If I have things like authentication, or some sort of header checking etc. it would be nice to be able to just slot a websocket request in there.

Feels like maybe Rack needs to have a notion of a 'connection' handler. The http1.x handler could roughly be thought of as

def handler(request)
  [status, headers, body] = middleware.first.call(request)
end

An http 'connection' handler might look like...

def handler(connection)
  request = HTTPRequest.new(connection)
  [status, headers, body] = middleware.first.call(request)
  deliver_response status, headers, body
end

A websocket 'connection' handler would maybe look a bit more like...

def handler(connection)
  socket = WebSocketRequest.new(connection)
  [status, headers, body] = websocket_middleware.first.call(request)
  if status > 299
    deliver_response status, headers, body
 else
    socket.accept
 end
end

The WebSocketRequest class or subclass could be responsible for dealing with messages

Could allow for a new top-level configuration block in .ru files, something like..

protocol 'http' do
  use AuthenticationMiddlware
end

protocol 'websocket' do
  use AuthenticationMiddlware
end

After trying that I wanted to type out...

protocol 'websocket' do
  handshake do
    use AuthenticationMiddleware
  end

  map '/git' do
    run WebsocketGitPackUploadHandler
  end

  map '/documents' do
    use StreamingJSONParser
    use StreamingXMLParser
    use StreamingYAMLParser
    run DocumentAPI
  end
end

Could very well be 3am nonsense, but I would like to see Rack figure out websockets.

@ioquatix
Copy link

+1 any progress on this?

@ioquatix
Copy link

What would be wrong with doing something like this? https://github.com/faye/faye-websocket-ruby

App = lambda do |env|
  if Faye::WebSocket.websocket?(env)
    ws = Faye::WebSocket.new(env)

    ws.on :message do |event|
      ws.send(event.data)
    end

    ws.on :close do |event|
      p [:close, event.code, event.reason]
      ws = nil
    end

    # Return async Rack response
    ws.rack_response

  else
    # Normal HTTP request
    [200, {'Content-Type' => 'text/plain'}, ['Hello']]
  end
end

@ioquatix
Copy link

Then, kill this line and pass it along like usual:

request.respond :bad_request, "WebSockets not supported"

Obviously, we'd want to use the WebSocket support you've developed in conjunction with Celluloid rather than Faye (which I believe uses EventMachine).

@tarcieri
Copy link
Member Author

There's a PR into Reel to use the websocket-driver from Faye

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants