Sha256: 9adfca35e74e8831a2c119eda7f3a2aa4f14fc5856e4b76043e4a065c8121f69

Contents?: true

Size: 1.95 KB

Versions: 2

Compression:

Stored size: 1.95 KB

Contents

# frozen_string_literal: true

require 'http/2'
require_relative './http2_stream'

module Polyphony
  module HTTP
    module Server
      # HTTP2 server adapter
      class HTTP2Adapter
        def self.upgrade_each(socket, opts, headers, &block)
          adapter = new(socket, opts, headers)
          adapter.each(&block)
        end

        def initialize(conn, opts, upgrade_headers = nil)
          @conn = conn
          @opts = opts
          @upgrade_headers = upgrade_headers

          @interface = ::HTTP2::Server.new
          @connection_fiber = Fiber.current
          @interface.on(:frame, &method(:send_frame))
          @streams = {}
        end

        def send_frame(data)
          @conn << data
        rescue Exception => e
          @connection_fiber.transfer e
        end

        UPGRADE_MESSAGE = <<~HTTP.gsub("\n", "\r\n")
          HTTP/1.1 101 Switching Protocols
          Connection: Upgrade
          Upgrade: h2c

        HTTP

        def upgrade
          @conn << UPGRADE_MESSAGE
          settings = @upgrade_headers['HTTP2-Settings']
          Fiber.current.schedule(nil)
          @interface.upgrade(settings, @upgrade_headers, '')
        ensure
          @upgrade_headers = nil
        end

        # Iterates over incoming requests
        def each(&block)
          @interface.on(:stream) { |stream| start_stream(stream, &block) }
          upgrade if @upgrade_headers

          while (data = @conn.readpartial(8192))
            @interface << data
            snooze
          end
        rescue SystemCallError, IOError
          # ignore
        ensure
          finalize_client_loop
        end

        def start_stream(stream, &block)
          stream = Stream.new(stream, &block)
          @streams[stream] = true
        end

        def finalize_client_loop
          @interface = nil
          @streams.each_key(&:stop)
          @conn.close
        end

        def close
          @conn.close
        end
      end
    end
  end
end

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
polyphony-http-0.28 lib/polyphony/http/server/http2.rb
polyphony-http-0.27 lib/polyphony/http/server/http2.rb