Class: Puppeteer::Bidi::Core::Request

Inherits:
EventEmitter show all
Includes:
Disposable::DisposableMixin
Defined in:
lib/puppeteer/bidi/core/request.rb,
sig/puppeteer/bidi/core/request.rbs

Overview

Request represents a network request

Constant Summary collapse

DESTINATION_RESOURCE_TYPES =

Returns:

  • (Object)
{
  "style" => "stylesheet",
  "document" => "document",
  "script" => "script",
  "image" => "image",
  "font" => "font",
  "audio" => "media",
  "video" => "media",
  "track" => "texttrack",
  "manifest" => "manifest",
  "iframe" => "document",
  "frame" => "document",
  "fetch" => "fetch",
  "object" => "other",
  "embed" => "other",
  "worker" => "other",
  "sharedworker" => "other",
  "serviceworker" => "other",
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Disposable::DisposableMixin

#dispose, #disposed?

Methods inherited from EventEmitter

#dispose, #disposed?, #emit, #off, #on, #once, #remove_all_listeners

Constructor Details

#initialize(browsing_context, event) ⇒ Request

Returns a new instance of Request.

Parameters:

  • browsing_context (Object)
  • event (Object)


43
44
45
46
47
48
49
50
51
52
53
# File 'lib/puppeteer/bidi/core/request.rb', line 43

def initialize(browsing_context, event)
  super()
  @browsing_context = browsing_context
  @event = event
  @error = nil
  @redirect = nil
  @response = nil
  @response_content_task = nil
  @request_body_task = nil
  @disposables = Disposable::DisposableStack.new
end

Instance Attribute Details

#browsing_contextObject (readonly)

Returns the value of attribute browsing_context.

Returns:

  • (Object)


41
42
43
# File 'lib/puppeteer/bidi/core/request.rb', line 41

def browsing_context
  @browsing_context
end

#errorObject (readonly)

Returns the value of attribute error.

Returns:

  • (Object)


41
42
43
# File 'lib/puppeteer/bidi/core/request.rb', line 41

def error
  @error
end

#responseObject (readonly)

Returns the value of attribute response.

Returns:

  • (Object)


41
42
43
# File 'lib/puppeteer/bidi/core/request.rb', line 41

def response
  @response
end

Class Method Details

.from(browsing_context, event) ⇒ Request

Create a request instance from a beforeRequestSent event

Parameters:

Returns:



35
36
37
38
39
# File 'lib/puppeteer/bidi/core/request.rb', line 35

def self.from(browsing_context, event)
  request = new(browsing_context, event)
  request.send(:initialize_request)
  request
end

Instance Method Details

#blocked?Boolean

Check if the request is blocked

Returns:

  • (Boolean)


117
118
119
# File 'lib/puppeteer/bidi/core/request.rb', line 117

def blocked?
  @event['isBlocked'] == true
end

#continue_request(url: nil, method: nil, headers: nil, cookies: nil, body: nil) ⇒ Async::Task[untyped]

Continue the request with optional modifications

Parameters:

  • url: (String, nil) (defaults to: nil)
  • method: (String, nil) (defaults to: nil)
  • headers: (Array[Hash[String, untyped]], nil) (defaults to: nil)
  • cookies: (Array[Hash[String, untyped]], nil) (defaults to: nil)
  • body: (Hash[String, untyped], nil) (defaults to: nil)

Returns:



158
159
160
161
162
163
164
165
166
167
# File 'lib/puppeteer/bidi/core/request.rb', line 158

def continue_request(url: nil, method: nil, headers: nil, cookies: nil, body: nil)
  params = { request: id }
  params[:url] = url if url
  params[:method] = method if method
  params[:headers] = headers if headers
  params[:cookies] = cookies if cookies
  params[:body] = body if body

  session.async_send_command('network.continueRequest', params)
end

#continue_with_auth(action:, credentials: nil) ⇒ Async::Task[untyped]

Continue with authentication

Parameters:

  • action: (String)
  • credentials: (Hash[String, untyped], nil) (defaults to: nil)

Returns:



247
248
249
250
251
252
253
254
255
# File 'lib/puppeteer/bidi/core/request.rb', line 247

def continue_with_auth(action:, credentials: nil)
  params = {
    request: id,
    action: action
  }
  params[:credentials] = credentials if action == 'provideCredentials'

  session.async_send_command('network.continueWithAuth', params)
end

#fail_requestAsync::Task[untyped]

Fail the request

Returns:



171
172
173
# File 'lib/puppeteer/bidi/core/request.rb', line 171

def fail_request
  session.async_send_command('network.failRequest', { request: id })
end

#fetch_post_dataAsync::Task[String?]

Fetch POST data for the request

Returns:



193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/puppeteer/bidi/core/request.rb', line 193

def fetch_post_data
  unless has_post_data?
    return Async do
      nil
    end
  end
  return @request_body_task if @request_body_task

  @request_body_task = Async do
    result = session.async_send_command('network.getData', {
      dataType: 'request',
      request: id
    }).wait

    bytes = result['bytes']
    if bytes['type'] == 'string'
      bytes['value']
    else
      raise "Collected request body data of type #{bytes['type']} is not supported"
    end
  end
end

#has_post_data?Boolean

Check if request has POST data

Returns:

  • (Boolean)


141
142
143
# File 'lib/puppeteer/bidi/core/request.rb', line 141

def has_post_data?
  (@event.dig('request', 'bodySize') || 0) > 0
end

#headersArray[Hash[String, untyped]]

Get request headers

Returns:

  • (Array[Hash[String, untyped]])


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

def headers
  @event.dig('request', 'headers') || []
end

#idString

Get request ID

Returns:

  • (String)


57
58
59
# File 'lib/puppeteer/bidi/core/request.rb', line 57

def id
  @event.dig('request', 'request')
end

#initialize_requestObject

Returns:

  • (Object)


270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
# File 'lib/puppeteer/bidi/core/request.rb', line 270

def initialize_request
  # Listen for browsing context closure
  @browsing_context.once(:closed) do |reason|
    @error = reason
    emit(:error, @error)
    dispose
  end

  # Listen for redirect
  session.on('network.beforeRequestSent') do |event|
    next unless event['context'] == @browsing_context.id
    next unless event.dig('request', 'request') == id

    # Check if this is a redirect
    previous_has_auth = @event.dig('request', 'headers')&.any? do |h|
      h['name'].downcase == 'authorization'
    end
    new_has_auth = event.dig('request', 'headers')&.any? do |h|
      h['name'].downcase == 'authorization'
    end
    is_after_auth = new_has_auth && !previous_has_auth

    next unless event['redirectCount'] == @event['redirectCount'] + 1 || is_after_auth

    @redirect = Request.from(@browsing_context, event)
    emit(:redirect, @redirect)
    dispose
  end

  # Listen for authentication required
  session.on('network.authRequired') do |event|
    next unless event['context'] == @browsing_context.id
    next unless event.dig('request', 'request') == id
    next unless event['isBlocked']

    emit(:authenticate, nil)
  end

  # Listen for fetch error
  session.on('network.fetchError') do |event|
    next unless event['context'] == @browsing_context.id
    next unless event.dig('request', 'request') == id
    next unless event['redirectCount'] == @event['redirectCount']

    @error = event['errorText']
    emit(:error, @error)
    dispose
  end

  # Listen for response started
  session.on('network.responseStarted') do |event|
    next unless event['context'] == @browsing_context.id
    next unless event.dig('request', 'request') == id
    next unless event['redirectCount'] == @event['redirectCount']

    @response = event['response']
    @event['request']['timings'] = event.dig('request', 'timings')
    emit(:response, @response)
  end

  # Listen for response completed
  session.on('network.responseCompleted') do |event|
    next unless event['context'] == @browsing_context.id
    next unless event.dig('request', 'request') == id
    next unless event['redirectCount'] == @event['redirectCount']

    @response = event['response']
    @event['request']['timings'] = event.dig('request', 'timings')
    emit(:success, @response)

    # Don't dispose if this is a redirect
    status = @response['status']
    dispose unless status >= 300 && status < 400
  end
end

#initiatorObject

Get request initiator information

Returns:

  • (Object)


104
105
106
107
108
109
110
111
112
113
# File 'lib/puppeteer/bidi/core/request.rb', line 104

def initiator
  initiator_data = @event['initiator']
  return nil unless initiator_data

  {
    **initiator_data,
    url: @event.dig('request', 'goog:resourceInitiator', 'url'),
    stack: @event.dig('request', 'goog:resourceInitiator', 'stack')
  }.compact
end

#last_redirectRequest?

Get the last redirect in the chain

Returns:



93
94
95
96
97
98
99
100
# File 'lib/puppeteer/bidi/core/request.rb', line 93

def last_redirect
  redirect_request = @redirect
  while redirect_request
    break unless redirect_request.redirect
    redirect_request = redirect_request.redirect
  end
  redirect_request
end

#methodString

Get request method

Returns:

  • (String)


69
70
71
# File 'lib/puppeteer/bidi/core/request.rb', line 69

def method
  @event.dig('request', 'method')
end

Get navigation ID if this is a navigation request

Returns:

  • (String, nil)


81
82
83
# File 'lib/puppeteer/bidi/core/request.rb', line 81

def navigation
  @event['navigation']
end

#perform_disposeObject

Returns:

  • (Object)


259
260
261
262
# File 'lib/puppeteer/bidi/core/request.rb', line 259

def perform_dispose
  @disposables.dispose
  super
end

#post_dataString?

Get POST data (non-standard)

Returns:

  • (String, nil)


135
136
137
# File 'lib/puppeteer/bidi/core/request.rb', line 135

def post_data
  @event.dig('request', 'goog:postData')
end

#provide_response(status_code: nil, reason_phrase: nil, headers: nil, body: nil) ⇒ Async::Task[untyped]

Provide a response for the request

Parameters:

  • status_code: (Integer, nil) (defaults to: nil)
  • reason_phrase: (String, nil) (defaults to: nil)
  • headers: (Array[Hash[String, untyped]], nil) (defaults to: nil)
  • body: (Hash[String, untyped], nil) (defaults to: nil)

Returns:



181
182
183
184
185
186
187
188
189
# File 'lib/puppeteer/bidi/core/request.rb', line 181

def provide_response(status_code: nil, reason_phrase: nil, headers: nil, body: nil)
  params = { request: id }
  params[:statusCode] = status_code if status_code
  params[:reasonPhrase] = reason_phrase if reason_phrase
  params[:headers] = headers if headers
  params[:body] = body if body

  session.async_send_command('network.provideResponse', params)
end

#redirectRequest?

Get redirect request if this request was redirected

Returns:



87
88
89
# File 'lib/puppeteer/bidi/core/request.rb', line 87

def redirect
  @redirect
end

#resource_typeString?

Get resource type (non-standard)

Returns:

  • (String, nil)


123
124
125
126
127
128
129
130
131
# File 'lib/puppeteer/bidi/core/request.rb', line 123

def resource_type
  resource_type = @event.dig('request', 'goog:resourceType')
  return resource_type if resource_type

  destination = @event.dig('request', 'destination')
  return nil unless destination

  DESTINATION_RESOURCE_TYPES.fetch(destination, destination)
end

#response_contentAsync::Task[String]

Get response content

Returns:



218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/puppeteer/bidi/core/request.rb', line 218

def response_content
  return @response_content_task if @response_content_task

  @response_content_task = Async do
    begin
      result = session.async_send_command('network.getData', {
        dataType: 'response',
        request: id
      }).wait

      bytes = result['bytes']
      if bytes['type'] == 'base64'
        [bytes['value']].pack('m0')
      else
        bytes['value']
      end
    rescue => e
      if e.message.include?('No resource with given identifier found')
        raise 'Could not load response body for this request. This might happen if the request is a preflight request.'
      end
      raise
    end
  end
end

#sessionObject

Returns:

  • (Object)


266
267
268
# File 'lib/puppeteer/bidi/core/request.rb', line 266

def session
  @browsing_context.user_context.browser.session
end

#timingHash[String, untyped]

Get timing information

Returns:

  • (Hash[String, untyped])


147
148
149
# File 'lib/puppeteer/bidi/core/request.rb', line 147

def timing
  @event.dig('request', 'timings') || {}
end

#urlString

Get request URL

Returns:

  • (String)


63
64
65
# File 'lib/puppeteer/bidi/core/request.rb', line 63

def url
  @event.dig('request', 'url')
end