Class: Puppeteer::HTTPRequest

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

Defined Under Namespace

Classes: AlreadyHandledError, InterceptionNotEnabledError, InternalAccessor

Constant Summary collapse

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:



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/puppeteer/http_request.rb', line 47

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 = {}
  @current_strategy = 'none'
  @current_priority = nil
  @intercept_actions = []
  @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.



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

def frame
  @frame
end

#headersObject (readonly)

Returns the value of attribute headers.



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

def headers
  @headers
end

#initiatorObject (readonly)

Returns the value of attribute initiator.



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

def initiator
  @initiator
end

#internalObject (readonly)

Returns the value of attribute internal.



74
75
76
# File 'lib/puppeteer/http_request.rb', line 74

def internal
  @internal
end

#methodObject (readonly)

Returns the value of attribute method.



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

def method
  @method
end

#post_dataObject (readonly)

Returns the value of attribute post_data.



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

def post_data
  @post_data
end

#resource_typeObject (readonly)

Returns the value of attribute resource_type.



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

def resource_type
  @resource_type
end

#responseObject (readonly)

Returns the value of attribute response.



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

def response
  @response
end

#urlObject (readonly)

Returns the value of attribute url.



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

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)


347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/puppeteer/http_request.rb', line 347

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 @current_priority.nil? || priority > @current_priority
    @current_strategy = :abort
    @current_priority = priority
  end
end

#abort_error_reasonObject



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

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)


203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/puppeteer/http_request.rb', line 203

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 @current_priority.nil? || priority > @current_priority
    @current_strategy = :continue
    @current_priority = priority
    return
  end

  if priority == @current_priority
    if @current_strategy == :abort || @current_strategy == :respond
      return
    end
    @current_strategy = :continue
  end
end

#continue_request_overridesObject

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



100
101
102
103
# File 'lib/puppeteer/http_request.rb', line 100

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)


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

def enqueue_intercept_action(pending_handler)
  @intercept_actions << pending_handler
end

#failureObject



163
164
165
166
167
# File 'lib/puppeteer/http_request.rb', line 163

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.



143
144
145
146
147
148
149
150
151
152
153
# File 'lib/puppeteer/http_request.rb', line 143

def finalize_interceptions
  @intercept_actions.each(&:call)
  case @intercept_resolution
  when :abort
    abort_impl(**@abort_error_reason)
  when :respond
    respond_impl(**@response_for_request)
  when :continue
    continue_impl(@continue_request_overrides)
  end
end

#inspectObject



77
78
79
80
81
82
83
# File 'lib/puppeteer/http_request.rb', line 77

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_resolutionObject

‘[strategy,priority]`. Strategy is one of: `abort`, `respond`, `continue`,

`disabled`, `none`, or `already-handled`.


121
122
123
124
125
126
127
128
129
# File 'lib/puppeteer/http_request.rb', line 121

def intercept_resolution
  if !@allow_interception
    ['disabled']
  elsif @interception_handled
    ['already-handled']
  else
    [@current_strategy, @current_priority]
  end
end

Returns:

  • (Boolean)


155
156
157
# File 'lib/puppeteer/http_request.rb', line 155

def navigation_request?
  @is_navigation_request
end

#redirect_chainObject



159
160
161
# File 'lib/puppeteer/http_request.rb', line 159

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)


268
269
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
# File 'lib/puppeteer/http_request.rb', line 268

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 @current_priority.nil? || priority > @current_priority
    @current_strategy = :respond
    @current_priority = priority
    return
  end

  if priority == @current_priority
    if @current_strategy == :abort
      return
    end
    @current_strategy = :respond
  end
end

#response_for_requestObject

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



107
108
109
110
# File 'lib/puppeteer/http_request.rb', line 107

def response_for_request
  assert_interception_allowed
  @response_for_request
end