Class: Puppeteer::HTTPRequest

Inherits:
Object
  • Object
show all
Includes:
DebugPrint, IfPresent
Defined in:
lib/puppeteer/http_request.rb

Defined Under Namespace

Classes: AlreadyHandledError, InterceptResolutionState, InterceptionNotEnabledError, InternalAccessor

Constant Summary collapse

DEFAULT_INTERCEPT_RESOLUTION_PRIORITY =
0
ERROR_REASONS =
{
  'aborted' => 'Aborted',
  'accessdenied' => 'AccessDenied',
  'addressunreachable' => 'AddressUnreachable',
  'blockedbyclient' => 'BlockedByClient',
  'blockedbyresponse' => 'BlockedByResponse',
  'connectionaborted' => 'ConnectionAborted',
  'connectionclosed' => 'ConnectionClosed',
  'connectionfailed' => 'ConnectionFailed',
  'connectionrefused' => 'ConnectionRefused',
  'connectionreset' => 'ConnectionReset',
  'internetdisconnected' => 'InternetDisconnected',
  'namenotresolved' => 'NameNotResolved',
  'timedout' => 'TimedOut',
  'failed' => 'Failed',
}.freeze
STATUS_TEXTS =

List taken from www.iana.org/assignments/http-status-codes/http-status-codes.xhtml with extra 306 and 418 codes.

{
  '100' => 'Continue',
  '101' => 'Switching Protocols',
  '102' => 'Processing',
  '103' => 'Early Hints',
  '200' => 'OK',
  '201' => 'Created',
  '202' => 'Accepted',
  '203' => 'Non-Authoritative Information',
  '204' => 'No Content',
  '205' => 'Reset Content',
  '206' => 'Partial Content',
  '207' => 'Multi-Status',
  '208' => 'Already Reported',
  '226' => 'IM Used',
  '300' => 'Multiple Choices',
  '301' => 'Moved Permanently',
  '302' => 'Found',
  '303' => 'See Other',
  '304' => 'Not Modified',
  '305' => 'Use Proxy',
  '306' => 'Switch Proxy',
  '307' => 'Temporary Redirect',
  '308' => 'Permanent Redirect',
  '400' => 'Bad Request',
  '401' => 'Unauthorized',
  '402' => 'Payment Required',
  '403' => 'Forbidden',
  '404' => 'Not Found',
  '405' => 'Method Not Allowed',
  '406' => 'Not Acceptable',
  '407' => 'Proxy Authentication Required',
  '408' => 'Request Timeout',
  '409' => 'Conflict',
  '410' => 'Gone',
  '411' => 'Length Required',
  '412' => 'Precondition Failed',
  '413' => 'Payload Too Large',
  '414' => 'URI Too Long',
  '415' => 'Unsupported Media Type',
  '416' => 'Range Not Satisfiable',
  '417' => 'Expectation Failed',
  '418' => 'I\'m a teapot',
  '421' => 'Misdirected Request',
  '422' => 'Unprocessable Entity',
  '423' => 'Locked',
  '424' => 'Failed Dependency',
  '425' => 'Too Early',
  '426' => 'Upgrade Required',
  '428' => 'Precondition Required',
  '429' => 'Too Many Requests',
  '431' => 'Request Header Fields Too Large',
  '451' => 'Unavailable For Legal Reasons',
  '500' => 'Internal Server Error',
  '501' => 'Not Implemented',
  '502' => 'Bad Gateway',
  '503' => 'Service Unavailable',
  '504' => 'Gateway Timeout',
  '505' => 'HTTP Version Not Supported',
  '506' => 'Variant Also Negotiates',
  '507' => 'Insufficient Storage',
  '508' => 'Loop Detected',
  '510' => 'Not Extended',
  '511' => 'Network Authentication Required',
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from IfPresent

#if_present

Methods included from DebugPrint

#debug_print, #debug_puts

Constructor Details

#initialize(client, frame, interception_id, allow_interception, event, redirect_chain) ⇒ HTTPRequest

Returns a new instance of HTTPRequest.

Parameters:



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/puppeteer/http_request.rb', line 86

def initialize(client, frame, interception_id, allow_interception, event, redirect_chain)
  @client = client
  @request_id = event['requestId']
  @is_navigation_request = event['requestId'] == event['loaderId'] && event['type'] == 'Document'
  @interception_id = interception_id
  @allow_interception = allow_interception
  @url = event['request']['url']
  @resource_type = event['type'].downcase
  @method = event['request']['method']
  @post_data = event['request']['postData']
  @frame = frame
  @redirect_chain = redirect_chain
  @continue_request_overrides = {}
  @intercept_resolution_state = InterceptResolutionState.none
  @intercept_handlers = []
  @initiator = event['initiator']

  @headers = {}
  event['request']['headers'].each do |key, value|
    @headers[key.downcase] = value
  end
  @from_memory_cache = false

  @internal = InternalAccessor.new(self)
end

Instance Attribute Details

#frameObject (readonly)

Returns the value of attribute frame.



113
114
115
# File 'lib/puppeteer/http_request.rb', line 113

def frame
  @frame
end

#headersObject (readonly)

Returns the value of attribute headers.



113
114
115
# File 'lib/puppeteer/http_request.rb', line 113

def headers
  @headers
end

#initiatorObject (readonly)

Returns the value of attribute initiator.



113
114
115
# File 'lib/puppeteer/http_request.rb', line 113

def initiator
  @initiator
end

#internalObject (readonly)

Returns the value of attribute internal.



112
113
114
# File 'lib/puppeteer/http_request.rb', line 112

def internal
  @internal
end

#methodObject (readonly)

Returns the value of attribute method.



113
114
115
# File 'lib/puppeteer/http_request.rb', line 113

def method
  @method
end

#post_dataObject (readonly)

Returns the value of attribute post_data.



113
114
115
# File 'lib/puppeteer/http_request.rb', line 113

def post_data
  @post_data
end

#resource_typeObject (readonly)

Returns the value of attribute resource_type.



113
114
115
# File 'lib/puppeteer/http_request.rb', line 113

def resource_type
  @resource_type
end

#responseObject (readonly)

Returns the value of attribute response.



113
114
115
# File 'lib/puppeteer/http_request.rb', line 113

def response
  @response
end

#urlObject (readonly)

Returns the value of attribute url.



113
114
115
# File 'lib/puppeteer/http_request.rb', line 113

def url
  @url
end

Instance Method Details

#abort(error_code: :failed, priority: nil) ⇒ Object

abort request on request interception.

Example:

page.on 'request' do |req|
  if req.url.include?("porn")
    req.abort
  else
    req.continue
  end
end

Parameters:

  • error_code (String|Symbol) (defaults to: :failed)


404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
# File 'lib/puppeteer/http_request.rb', line 404

def abort(error_code: :failed, priority: nil)
  # Request interception is not supported for data: urls.
  return if @url.start_with?('data:')

  error_reason = ERROR_REASONS[error_code.to_s]
  unless error_reason
    raise ArgumentError.new("Unknown error code: #{error_code}")
  end
  assert_interception_allowed
  assert_interception_not_handled

  if priority.nil?
    abort_impl(error_reason)
  end
  @abort_error_reason = error_reason

  if @intercept_resolution_state.priority_unspecified? || priority > @intercept_resolution_state.priority
    @intercept_resolution_state = InterceptResolutionState.abort(priority: priority)
  end
end

#abort_error_reasonObject



151
152
153
154
# File 'lib/puppeteer/http_request.rb', line 151

def abort_error_reason
  assert_interception_allowed
  @abort_error_reason
end

#continue(url: nil, method: nil, post_data: nil, headers: nil, priority: nil) ⇒ Object

proceed request on request interception.

Example:

page.on 'request' do |req|
  # Override headers
  headers = req.headers.merge(
    foo: 'bar', # set "foo" header
    origin: nil, # remove "origin" header
  )
  req.continue(headers: headers)
end

Parameters:

  • error_code (String|Symbol)


257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
# File 'lib/puppeteer/http_request.rb', line 257

def continue(url: nil, method: nil, post_data: nil, headers: nil, priority: nil)
  # Request interception is not supported for data: urls.
  return if @url.start_with?('data:')

  assert_interception_allowed
  assert_interception_not_handled

  overrides = {
    url: url,
    method: method,
    postData: post_data,
    headers: headers_to_array(headers),
  }.compact

  if priority.nil?
    continue_impl(overrides)
    return
  end

  @continue_request_overrides = overrides
  if @intercept_resolution_state.priority_unspecified? || priority > @intercept_resolution_state.priority
    @intercept_resolution_state = InterceptResolutionState.continue(priority: priority)
    return
  end

  if priority == @intercept_resolution_state.priority
    if @intercept_resolution_state.action == :abort || @intercept_resolution_state.action == :respond
      return
    end
    @intercept_resolution_state = InterceptResolutionState.continue(priority: priority)
  end
end

#continue_request_overridesObject

if the interception is allowed to continue (ie, ‘abort()` and `respond()` aren’t called).



138
139
140
141
# File 'lib/puppeteer/http_request.rb', line 138

def continue_request_overrides
  assert_interception_allowed
  @continue_request_overrides
end

#enqueue_intercept_action(pending_handler) ⇒ Object

Adds an async request handler to the processing queue. Deferred handlers are not guaranteed to execute in any particular order, but they are guarnateed to resolve before the request interception is finalized.

Parameters:

  • pending_handler (Proc)


185
186
187
# File 'lib/puppeteer/http_request.rb', line 185

def enqueue_intercept_action(pending_handler)
  @intercept_handlers << pending_handler
end

#failureObject



211
212
213
214
215
# File 'lib/puppeteer/http_request.rb', line 211

def failure
  if_present(@failure_text) do |failure_text|
    { errorText: @failure_text }
  end
end

#finalize_interceptionsObject

Awaits pending interception handlers and then decides how to fulfill the request interception.



191
192
193
194
195
196
197
198
199
200
201
# File 'lib/puppeteer/http_request.rb', line 191

def finalize_interceptions
  @intercept_handlers.each(&:call)
  case intercept_resolution_state.action
  when 'abort'
    abort_impl(**@abort_error_reason)
  when 'respond'
    respond_impl(**@response_for_request)
  when 'continue'
    continue_impl(@continue_request_overrides)
  end
end

#inspectObject



115
116
117
118
119
120
121
# File 'lib/puppeteer/http_request.rb', line 115

def inspect
  values = i[request_id method url].map do |sym|
    value = instance_variable_get(:"@#{sym}")
    "@#{sym}=#{value}"
  end
  "#<Puppeteer::HTTPRequest #{values.join(' ')}>"
end

#intercept_resolution_handled?Boolean

Returns:

  • (Boolean)


175
176
177
# File 'lib/puppeteer/http_request.rb', line 175

def intercept_resolution_handled?
  @interception_handled
end

#intercept_resolution_stateObject



165
166
167
168
169
170
171
172
173
# File 'lib/puppeteer/http_request.rb', line 165

def intercept_resolution_state
  if !@allow_interception
    InterceptResolutionState.disabled
  elsif @interception_handled
    InterceptResolutionState.already_handled
  else
    @intercept_resolution_state.dup
  end
end

Returns:

  • (Boolean)


203
204
205
# File 'lib/puppeteer/http_request.rb', line 203

def navigation_request?
  @is_navigation_request
end

#redirect_chainObject



207
208
209
# File 'lib/puppeteer/http_request.rb', line 207

def redirect_chain
  @redirect_chain.dup
end

#respond(status: nil, headers: nil, content_type: nil, body: nil, priority: nil) ⇒ Object

Mocking response.

Example:

page.on 'request' do |req|
  req.respond(
    status: 404,
    content_type: 'text/plain',
    body: 'Not Found!'
  )
end

Parameters:

  • status (Integer) (defaults to: nil)
  • headers (Hash<String, String>) (defaults to: nil)
  • content_type (String) (defaults to: nil)
  • body (String) (defaults to: nil)


321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
# File 'lib/puppeteer/http_request.rb', line 321

def respond(status: nil, headers: nil, content_type: nil, body: nil, priority: nil)
  # Mocking responses for dataURL requests is not currently supported.
  return if @url.start_with?('data:')

  assert_interception_allowed
  assert_interception_not_handled

  if priority.nil?
    respond_impl(status: status, headers: headers, content_type: content_type, body: body)
    return
  end

  @response_for_request = {
    status: status,
    headers: headers,
    content_type: content_type,
    body: body,
  }

  if @intercept_resolution_state.priority_unspecified? || priority > @intercept_resolution_state.priority
    @intercept_resolution_state = InterceptResolutionState.respond(priority: priority)
    return
  end

  if priority == @intercept_resolution_state.priority
    if @intercept_resolution_state.action == :abort
      return
    end
    @intercept_resolution_state = InterceptResolutionState.respond(priority: priority)
  end
end

#response_for_requestObject

interception is allowed to respond (ie, ‘abort()` is not called).



145
146
147
148
# File 'lib/puppeteer/http_request.rb', line 145

def response_for_request
  assert_interception_allowed
  @response_for_request
end