Sha256: de58060d791457cf362892b55a668f1ec4c430c1b8a05f0832f29fbbea99c7c9

Contents?: true

Size: 1.45 KB

Versions: 1

Compression:

Stored size: 1.45 KB

Contents

# frozen_string_literal: true

module LiteCable
  module Server
    # Rack middleware to hijack the socket
    class Middleware
      class HijackNotAvailable < RuntimeError; end

      def initialize(_app, connection_class:)
        @connection_class = connection_class
        @heart_beat = HeartBeat.new
      end

      def call(env)
        return [404, { 'Content-Type' => 'text/plain' }, ['Not Found']] unless
          env["HTTP_UPGRADE"] == 'websocket'

        raise HijackNotAvailable unless env['rack.hijack']

        env['rack.hijack'].call
        handshake = send_handshake(env)

        socket = ClientSocket::Base.new env, env['rack.hijack_io'], handshake.version
        init_connection socket
        init_heartbeat socket
        socket.listen
        [-1, {}, []]
      end

      private

      def send_handshake(env)
        handshake = WebSocket::Handshake::Server.new(
          protocols: LiteCable::INTERNAL[:protocols]
        )

        handshake.from_rack env
        env['rack.hijack_io'].write handshake.to_s
        handshake
      end

      def init_connection(socket)
        connection = @connection_class.new(socket)

        socket.onopen { connection.handle_open }
        socket.onclose { connection.handle_close }
        socket.onmessage { |data| connection.handle_command(data) }
      end

      def init_heartbeat(socket)
        @heart_beat.add(socket)
        socket.onclose { @heart_beat.remove(socket) }
      end
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
litecable-0.5.0 lib/lite_cable/server/middleware.rb