@ledsun blog

無味の味は佳境に入らざればすなわち知れず

Async::WebSocket gemの素振り その4

Async::WebSocket gemの素振り その3 - @ledsun blog にて、ブロック呼び出しが入れ子になっていたのを解消しました。 次にAsync::WebSocket::Adapters::HTTP.openを展開します。

require 'async/websocket/response'
require 'async/websocket/connection'
require 'protocol/websocket/framer'
require 'protocol/websocket/extensions'
require "protocol/rack/request"
require "protocol/rack/adapter"

class App
  def self.websocket?(request)
    Array(request.protocol).any? { |e| e.casecmp?(::Protocol::WebSocket::Headers::PROTOCOL) }
  end

  def self.open(request)
    if websocket?(request)

      response = ::Async::WebSocket::Response.for(request, protocol: nil) do |stream|
        framer = ::Protocol::WebSocket::Framer.new(stream)
        connection = ::Async::WebSocket::Connection.call(framer, nil, ::Protocol::WebSocket::Extensions::Server.default)

        yield connection
      ensure
        connection&.close
        stream.close
      end

      # Once we get to this point, we no longer need to hold on to the request:
      request = nil

      return response
    end
  end

  def self.call(env)
    req = ::Protocol::Rack::Request[env]

    res = open(req) do |conn|
      # Echo back!
      while message = conn.read
        conn.write message
      end
    end

    Protocol::Rack::Adapter.make_response(env, res)
  end
end

run App

また、ブロック呼び出しの入れ子が増えてしまいました。