Class: Puppeteer::Bidi::Transport

Inherits:
Object
  • Object
show all
Defined in:
lib/puppeteer/bidi/transport.rb,
sig/puppeteer/bidi/transport.rbs

Overview

Transport handles WebSocket communication with BiDi server This is the lowest layer that manages raw WebSocket send/receive

Defined Under Namespace

Classes: ClosedError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(url) ⇒ Transport

Returns a new instance of Transport.

Parameters:

  • url (Object)


19
20
21
22
23
24
25
26
27
28
29
# File 'lib/puppeteer/bidi/transport.rb', line 19

def initialize(url)
  # BiDi WebSocket endpoint requires /session path
  @url = url.end_with?('/session') ? url : "#{url}/session"
  @endpoint = nil
  @connection = nil
  @task = nil
  @connected = false
  @closed = false
  @on_message = nil
  @on_close = nil
end

Instance Attribute Details

#urlObject (readonly)

Returns the value of attribute url.

Returns:

  • (Object)


17
18
19
# File 'lib/puppeteer/bidi/transport.rb', line 17

def url
  @url
end

Instance Method Details

#async_send_message(message) ⇒ Object

Send a message to BiDi server

Parameters:

  • message (Object)

Returns:

  • (Object)


58
59
60
61
62
63
64
65
66
67
# File 'lib/puppeteer/bidi/transport.rb', line 58

def async_send_message(message)
  raise ClosedError, 'Transport is closed' if @closed

  debug_print_send(message)
  json = JSON.generate(message)
  Async do
    @connection&.write(json)
    @connection&.flush
  end
end

#closeObject

Close the WebSocket connection

Returns:

  • (Object)


80
81
82
83
84
85
86
87
# File 'lib/puppeteer/bidi/transport.rb', line 80

def close
  return if @closed

  @closed = true
  @connection&.close
  @on_close&.call
  @task&.stop
end

#closed?Boolean

Returns:

  • (Boolean)


89
90
91
# File 'lib/puppeteer/bidi/transport.rb', line 89

def closed?
  @closed
end

#connectObject

Connect to WebSocket and start receiving messages

Returns:

  • (Object)


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/puppeteer/bidi/transport.rb', line 32

def connect
  connection_promise = Async::Promise.new
  @task = Async do |task|
    endpoint = Async::HTTP::Endpoint.parse(@url)

    # Connect to WebSocket - this matches minibidi's implementation
    Async::WebSocket::Client.connect(endpoint) do |connection|
      @connection = connection
      @connected = true
      connection_promise.resolve(connection)

      # Start message receiving loop (this will block until connection closes)
      receive_loop(connection)
    end
  rescue => e
    warn "Transport connect error: #{e.class} - #{e.message}"
    warn e.backtrace.join("\n")
    connection_promise.reject(e)
    close
  ensure
    @connected = false
  end
  connection_promise
end

#connected?Boolean

Returns:

  • (Boolean)


93
94
95
# File 'lib/puppeteer/bidi/transport.rb', line 93

def connected?
  @connected && !@closed
end

#debug_print_receive(message) ⇒ Object

Parameters:

  • message (Object)

Returns:

  • (Object)


126
127
128
129
130
# File 'lib/puppeteer/bidi/transport.rb', line 126

def debug_print_receive(message)
  if %w[1 true].include?(ENV['DEBUG_PROTOCOL'])
    puts "RECV << #{JSON.generate(message)}"
  end
end

#debug_print_send(message) ⇒ Object

Parameters:

  • message (Object)

Returns:

  • (Object)


120
121
122
123
124
# File 'lib/puppeteer/bidi/transport.rb', line 120

def debug_print_send(message)
  if %w[1 true].include?(ENV['DEBUG_PROTOCOL'])
    puts "SEND >> #{JSON.generate(message)}"
  end
end

#on_close(&block) ⇒ void

This method returns an undefined value.

Register close handler



75
76
77
# File 'lib/puppeteer/bidi/transport.rb', line 75

def on_close(&block)
  @on_close = block
end

#on_message(&block) ⇒ void

This method returns an undefined value.

Register message handler



70
71
72
# File 'lib/puppeteer/bidi/transport.rb', line 70

def on_message(&block)
  @on_message = block
end

#receive_loop(connection) ⇒ Object

Parameters:

  • connection (Object)

Returns:

  • (Object)


99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/puppeteer/bidi/transport.rb', line 99

def receive_loop(connection)
  while (message = connection.read)
    next if message.nil?

    Async do
      data = JSON.parse(message.to_str)
      debug_print_receive(data)
      @on_message&.call(data)
    rescue JSON::ParserError => e
      warn "Failed to parse BiDi message: #{e.message}"
    end
  end
rescue IOError, Errno::ECONNRESET, Errno::EPIPE
  # Connection closed - this is expected during shutdown, no need to warn
rescue => e
  # Only warn for unexpected errors if we weren't intentionally closed
  warn "Transport receive error: #{e.message}" unless @closed
ensure
  close unless @closed
end