Class: Puppeteer::HTTPRequest
- Inherits:
-
Object
- Object
- Puppeteer::HTTPRequest
- 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
-
#client ⇒ Object
readonly
Returns the value of attribute client.
-
#frame ⇒ Object
readonly
Returns the value of attribute frame.
-
#initiator ⇒ Object
readonly
Returns the value of attribute initiator.
-
#internal ⇒ Object
readonly
Returns the value of attribute internal.
-
#method ⇒ Object
readonly
Returns the value of attribute method.
-
#post_data ⇒ Object
readonly
Returns the value of attribute post_data.
-
#resource_type ⇒ Object
readonly
Returns the value of attribute resource_type.
-
#response ⇒ Object
readonly
Returns the value of attribute response.
-
#url ⇒ Object
readonly
Returns the value of attribute url.
Instance Method Summary collapse
-
#abort(error_code: :failed, priority: nil) ⇒ Object
abort request on request interception.
- #abort_error_reason ⇒ Object
-
#continue(url: nil, method: nil, post_data: nil, headers: nil, priority: nil) ⇒ Object
proceed request on request interception.
-
#continue_request_overrides ⇒ Object
if the interception is allowed to continue (ie, ‘abort()` and `respond()` aren’t called).
-
#enqueue_intercept_action(pending_handler) ⇒ Object
Adds an async request handler to the processing queue.
- #failure ⇒ Object
- #fetch_post_data ⇒ Object
-
#finalize_interceptions ⇒ Object
Awaits pending interception handlers and then decides how to fulfill the request interception.
- #has_post_data? ⇒ Boolean
- #headers ⇒ Object
-
#initialize(client, frame, interception_id, allow_interception, event, redirect_chain) ⇒ HTTPRequest
constructor
A new instance of HTTPRequest.
- #inspect ⇒ Object
- #intercept_resolution_handled? ⇒ Boolean
- #intercept_resolution_state ⇒ Object
- #navigation_request? ⇒ Boolean
- #redirect_chain ⇒ Object
-
#respond(status: nil, headers: nil, content_type: nil, body: nil, priority: nil) ⇒ Object
Mocking response.
-
#response_for_request ⇒ Object
interception is allowed to respond (ie, ‘abort()` is not called).
- #update_headers(headers) ⇒ Object
Methods included from IfPresent
Methods included from DebugPrint
Constructor Details
#initialize(client, frame, interception_id, allow_interception, event, redirect_chain) ⇒ HTTPRequest
Returns a new instance of HTTPRequest.
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/puppeteer/http_request.rb', line 94 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'] url_fragment = event.dig('request', 'urlFragment') @url += url_fragment if url_fragment resource_type = event['type'] || event['resourceType'] || 'other' @resource_type = resource_type.downcase @method = event['request']['method'] @post_data = parse_post_data(event) has_post_data = event.dig('request', 'hasPostData') @has_post_data = has_post_data.nil? ? !@post_data.nil? : has_post_data @frame = frame @redirect_chain = redirect_chain @continue_request_overrides = {} @intercept_resolution_state = InterceptResolutionState.none @interception_handled = false @intercept_handlers = [] @initiator = event['initiator'] @headers = {} update_headers(event.dig('request', 'headers') || {}) @from_memory_cache = false @internal = InternalAccessor.new(self) end |
Instance Attribute Details
#client ⇒ Object (readonly)
Returns the value of attribute client.
125 126 127 |
# File 'lib/puppeteer/http_request.rb', line 125 def client @client end |
#frame ⇒ Object (readonly)
Returns the value of attribute frame.
125 126 127 |
# File 'lib/puppeteer/http_request.rb', line 125 def frame @frame end |
#initiator ⇒ Object (readonly)
Returns the value of attribute initiator.
125 126 127 |
# File 'lib/puppeteer/http_request.rb', line 125 def initiator @initiator end |
#internal ⇒ Object (readonly)
Returns the value of attribute internal.
124 125 126 |
# File 'lib/puppeteer/http_request.rb', line 124 def internal @internal end |
#method ⇒ Object (readonly)
Returns the value of attribute method.
125 126 127 |
# File 'lib/puppeteer/http_request.rb', line 125 def method @method end |
#post_data ⇒ Object (readonly)
Returns the value of attribute post_data.
125 126 127 |
# File 'lib/puppeteer/http_request.rb', line 125 def post_data @post_data end |
#resource_type ⇒ Object (readonly)
Returns the value of attribute resource_type.
125 126 127 |
# File 'lib/puppeteer/http_request.rb', line 125 def resource_type @resource_type end |
#response ⇒ Object (readonly)
Returns the value of attribute response.
125 126 127 |
# File 'lib/puppeteer/http_request.rb', line 125 def response @response end |
#url ⇒ Object (readonly)
Returns the value of attribute url.
125 126 127 |
# File 'lib/puppeteer/http_request.rb', line 125 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
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 |
# File 'lib/puppeteer/http_request.rb', line 480 def abort(error_code: :failed, priority: nil) 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 return unless can_be_intercepted? if priority.nil? return 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_reason ⇒ Object
203 204 205 206 |
# File 'lib/puppeteer/http_request.rb', line 203 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
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 345 |
# File 'lib/puppeteer/http_request.rb', line 316 def continue(url: nil, method: nil, post_data: nil, headers: nil, priority: nil) assert_interception_allowed assert_interception_not_handled return unless can_be_intercepted? overrides = { url: url, method: method, post_data: post_data, headers: 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_overrides ⇒ Object
if the interception is allowed to continue (ie, ‘abort()` and `respond()` aren’t called).
190 191 192 193 |
# File 'lib/puppeteer/http_request.rb', line 190 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.
237 238 239 |
# File 'lib/puppeteer/http_request.rb', line 237 def enqueue_intercept_action(pending_handler) @intercept_handlers << pending_handler end |
#failure ⇒ Object
267 268 269 270 271 |
# File 'lib/puppeteer/http_request.rb', line 267 def failure if_present(@failure_text) do |failure_text| { errorText: @failure_text } end end |
#fetch_post_data ⇒ Object
143 144 145 146 147 148 149 |
# File 'lib/puppeteer/http_request.rb', line 143 def fetch_post_data response = @client.('Network.getRequestPostData', requestId: @request_id) response['postData'] rescue => err debug_puts(err) nil end |
#finalize_interceptions ⇒ Object
Awaits pending interception handlers and then decides how to fulfill the request interception.
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/puppeteer/http_request.rb', line 243 def finalize_interceptions @intercept_handlers.each do |handler| Puppeteer::AsyncUtils.await(handler.call) end @intercept_handlers = [] case intercept_resolution_state.action when 'abort' abort_impl(@abort_error_reason) when 'respond' raise "Response is missing for the interception" if @response_for_request.nil? respond_impl(**@response_for_request) when 'continue' continue_impl(@continue_request_overrides) end end |
#has_post_data? ⇒ Boolean
138 139 140 |
# File 'lib/puppeteer/http_request.rb', line 138 def has_post_data? @has_post_data end |
#headers ⇒ Object
133 134 135 |
# File 'lib/puppeteer/http_request.rb', line 133 def headers @headers.dup end |
#inspect ⇒ Object
151 152 153 154 155 156 157 |
# File 'lib/puppeteer/http_request.rb', line 151 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
227 228 229 |
# File 'lib/puppeteer/http_request.rb', line 227 def intercept_resolution_handled? @interception_handled end |
#intercept_resolution_state ⇒ Object
217 218 219 220 221 222 223 224 225 |
# File 'lib/puppeteer/http_request.rb', line 217 def intercept_resolution_state if !@allow_interception InterceptResolutionState.disabled elsif @interception_handled InterceptResolutionState.already_handled else @intercept_resolution_state.dup end end |
#navigation_request? ⇒ Boolean
259 260 261 |
# File 'lib/puppeteer/http_request.rb', line 259 def @is_navigation_request end |
#redirect_chain ⇒ Object
263 264 265 |
# File 'lib/puppeteer/http_request.rb', line 263 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
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 |
# File 'lib/puppeteer/http_request.rb', line 388 def respond(status: nil, headers: nil, content_type: nil, body: nil, priority: nil) assert_interception_allowed assert_interception_not_handled return unless can_be_intercepted? 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, }.compact 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_request ⇒ Object
interception is allowed to respond (ie, ‘abort()` is not called).
197 198 199 200 |
# File 'lib/puppeteer/http_request.rb', line 197 def response_for_request assert_interception_allowed @response_for_request end |
#update_headers(headers) ⇒ Object
127 128 129 130 131 |
# File 'lib/puppeteer/http_request.rb', line 127 def update_headers(headers) headers.each do |key, value| @headers[key.downcase] = value end end |