# Request-Interception

## Example Script

    import asyncio
    import json
    from selenium_driverless import webdriver
    from selenium_driverless.scripts.network_interceptor import NetworkInterceptor, InterceptedRequest, InterceptedAuth, \
        RequestPattern, RequestStages

    async def on_request(data: InterceptedRequest):
        if data.request.url == "https://httpbin.org/post":
            await data.continue_request(url="https://httpbin.org/basic-auth/user/pass", intercept_response=True)

    async def main():
        async with webdriver.Chrome(max_ws_size=2 ** 30) as driver:

            async with NetworkInterceptor(driver, on_request=on_request, patterns=[RequestPattern.AnyRequest],
                                          intercept_auth=True) as interceptor:

                asyncio.ensure_future(driver.get("https://httpbin.org/post", wait_load=False))
                async for data in interceptor:
                    if data.request.url == "https://httpbin.org/basic-auth/user/pass":
                        if isinstance(data, InterceptedAuth):
                            # iteration should take virtually zero time, as that would block other requests
                            asyncio.ensure_future(data.continue_auth(username="user", password="pass"))
                        elif data.stage == RequestStages.Response:
                            print(json.loads(await data.body))
                            break

    asyncio.run(main())

## API

class selenium_driverless.scripts.network_interceptor.NetworkInterceptor(target, on_request=None, on_response=None, on_auth=None, patterns=None, intercept_auth=False, bypass_service_workers=False)
  __init__(target, on_request=None, on_response=None, on_auth=None, patterns=None, intercept_auth=False, bypass_service_workers=False)
    Parameters:

      - target (`Union`[`Chrome`, `Target`]) – the Target or Driver, on which requests get intercepted

      - on_request (`Optional`[`Callable`[[`InterceptedRequest`], `Awaitable`[`None`]]]) – onRequest callback

      - on_response (`Optional`[`Callable`[[`InterceptedRequest`], `Awaitable`[`None`]]]) – onResponse callback

      - on_auth (`Optional`[`Callable`[[`InterceptedRequest`], `Awaitable`[`None`]]]) – onAuth callback

      - patterns (`Union`[`List`[`Dict`[`str`, `str`]], `List`[`RequestPattern`], `None`]) – the request patterns to intercept

      - intercept_auth (`bool`) – whether to intercept authentification

      - bypass_service_workers (`bool`) – whether to bypass service workers for a single Target

  __aiter__()

    iterate using `async for` over requests

    Example

        from selenium_driverless.scripts.network_interceptor import InterceptedRequest, RequestStages

        # ... some code
        async for data in interceptor:
            url = data.request.url
            if isinstance(data, InterceptedRequest):
                data.stage == RequestStages.Request:
                    print("Request:"+url)
                else:
                    print("Response:"+url)
            else:
                print("Authentification:"+url)

    Return type:

      `AsyncIterator`[`Union`[`InterceptedRequest`, `InterceptedAuth`]]

    Warning

    iterations should virtually take zero time, you might use `asyncio.ensure_future` where possible

  property patterns: List[Dict[str, str]]

    patters to intercept

  property target: Target | BaseTarget

    the Target, on which requests get intercepted

class selenium_driverless.scripts.network_interceptor.InterceptedRequest(params, target)
  property target: Target | BaseTarget

    the target

  property stage: Literal[0, 1]

    one of `RequestStages.Request`, `RequestStages.Response` 0 => Request 1 => Response

  property is_redirect

    if the response is a redirect (response_status_code in [301, 302, 303, 307, 308])

  property params: dict

    the parameters from Fetch.requestPaused as a dict

  property frame_id: str

    the `Page.FrameId` of the frame that initiated the request

  property request: Request

    the corresponding request

  property id: str

    `Fetch.RequestId`

  property resource_type: str

    `Network.resourceType`

  property network_id: str | None

    the `Network.RequestId` if a corresponding `Network.requestWillBeSent` event had been fired

  property response_error_reason: str | None

    response error-reason at response stage

  property response_headers: List[Dict[str, str]] | None

    the headers at response stage

  property response_status_code: int | None

    the status code at response stage

  property response_status_text: str | None

    the status text at response stage

  property redirected_id: str | None

    `Fetch.requestId` reference id to the request that caused the redirect

  property body: bytes | None

    async get the response body for a request

    Note

    this uses network and might take some time

  async bypass_browser(auth=None, allow_redirects=True, compress=None, proxy=None, proxy_auth=None, timeout=None)

    bypass browser by making the request externally

    Warning

    this method does not change the TLS fingerprint accordingly and is technically detectable

  async continue_request(headers=None, method=None, post_data=None, url=None, intercept_response=None)

    continue the request. You might use `InterceptedRequest.fulfill` to provide a response body

    Parameters:

      - headers (`Optional`[`List`[`Dict`[`str`, `str`]]]) – array of {“name”:name, “value”:value}, mind header order

      - method (`Optional`[`str`]) – the method of the request

      - post_data (`Union`[`str`, `bytes`, `None`]) – the binary post data to provide

      - url (`Optional`[`str`]) – the url to continue the request with, change not observable by the page

      - intercept_response (`Optional`[`bool`]) – overrides response interception behavior for this request

  async continue_response(response_headers=None, binary_response_headers=None, response_code=None, response_phrase=None)

    continue the response. You might use `By` to provide a response body

    Parameters:

      - response_code (`Optional`[`int`]) – response code

      - binary_response_headers (`Optional`[`bytes`]) – headers as a -separated series of name: value pairs, treated as base64 encode if a string is passed,

      - response_headers (`Optional`[`List`[`Dict`[`str`, `str`]]]) – array of {“name”:name, “value”:value}, mind header order

      - response_phrase (`Optional`[`str`]) – response phrase (`"OK"` for `response_code=200`)

  async resume()

    continue the request or response doesn’t raise id the request is canceled or already done

  async fail_request(error_reason)

    fail the request or response

    Parameters:

      error_reason (`Literal`[`'Failed'`, `'Aborted'`, `'TimedOut'`, `'AccessDenied'`, `'ConnectionClosed'`, `'ConnectionReset'`, `'ConnectionRefused'`, `'ConnectionAborted'`, `'ConnectionFailed'`, `'NameNotResolved'`, `'InternetDisconnected'`, `'AddressUnreachable'`, `'BlockedByClient'`, `'BlockedByResponse'`]) – the specified reason for the request failing

  async fulfill(response_code, binary_response_headers=None, body=None, response_headers=None, response_phrase=None)

    fulfill the request or response

    Parameters:

      - response_code (`int`) – response code

      - body (`Union`[`str`, `bytes`, `None`]) – the response body

      - binary_response_headers (`Optional`[`str`]) – headers as a -separated series of name: value pairs, treated as base64 encode if a string is passed,

      - response_headers (`Optional`[`List`[`Dict`[`str`, `str`]]]) – array of {“name”:name, “value”:value}, mind header order

      - response_phrase (`Optional`[`str`]) – response phrase (`"OK"` for `response_code=200`)

class selenium_driverless.scripts.network_interceptor.InterceptedAuth(params, target)
  property request: Request

    the Request, for which auth is required

  property id: str

    the `Fetch.RequestId`

  property frame_id: str

    the `Page.FrameId` from which the request has been initiated

  property params: dict

    the parameters from Fetch.authRequired as a dict

  property target: Target | BaseTarget

    the target

  property resource_type: str

    the Network.ResourceType

  property auth_challenge: AuthChallenge

    the AuthChallenge

  async continue_auth(response='Default', username=None, password=None)

    continue the auth

    Parameters:

      - response (`Literal`[`'Default'`, `'CancelAuth'`, `'ProvideCredentials'`]) – “Default” by default, automatically set to “ProvideCredentials”, if username or password specified

      - username (`Optional`[`str`]) – username for the auth

      - password (`Optional`[`str`]) – password for the auth

  async resume()

    continue the auth doesn’t raise id the request is canceled or already done

  async cancel()

    cancel the auth

class selenium_driverless.scripts.network_interceptor.AuthChallenge(params, target)
  property target: Target | BaseTarget

    the target

  property params: dict

    the parameters from Fetch.AuthChallenge as a dict

  property source: Literal['Server', 'Proxy']

    Source of the authentication challenge

  property origin: str

    Origin of the challenger.

  property scheme: str

    The authentication scheme used, such as basic or digest

  property realm: str

    corresponding value for `Please enter your username and password for <realm name>:`

class selenium_driverless.scripts.network_interceptor.Request(params, target)
  property target: Target | BaseTarget

    the target

  property params: dict

    the parameters from Network.Request as a dict

  property url: str

    Request URL (without fragment).

  property url_fragment: str | None

    Fragment of the requested URL starting with hash, if present.

  property method: str | None

    HTTP request method.

  property headers: Dict[str, str]

    Request / response headers as keys / values of JSON object.

  property post_data: str | None

    HTTP POST request data

  property has_post_data: bool | None

    True when the request has POST data. Note that postData might still be omitted when this flag is true when the data is too long.

  property post_data_entries: List[str] | None

    an array of Network.PostDataEntry

  property mixed_content_type: Literal['blockable', 'optionally-blockable', 'none', None]

    The mixed content type of the request.

  property initial_priority: Literal['VeryLow', 'Low', 'Medium', 'High', 'VeryHigh', None]

    Priority of the resource request at the time request is sent.

  property referrer_policy: Literal['unsafe-url', 'no-referrer-when-downgrade', 'no-referrer', 'origin', 'origin-when-cross-origin', 'same-origin', 'strict-origin', 'strict-origin-when-cross-origin']

    The referrer policy of the request, as defined in w3.org/TR/referrer-policy

  property is_link_preload: bool | None

    Whether is loaded via link preload.

  property trust_token_params: dict | None

    see Network.TrustTokenParams for reference

  property is_same_site: bool | None

    True if this resource request is considered to be the ‘same site’ as the request corresponding to the main frame.

class selenium_driverless.scripts.network_interceptor.RequestStages
  Request = 0

    stage at request

  Response = 1

    stage at response

class selenium_driverless.scripts.network_interceptor.RequestPattern(value)

  An enumeration.

  AnyRequest = {'requestStage': 'Request', 'urlPattern': '*'}

    pattern for any request

  AnyResponse = {'requestStage': 'Response', 'urlPattern': '*'}

    pattern for any response

  static new(url_pattern=None, resource_type=None, request_stage=None)

    create a new request pattern

class selenium_driverless.scripts.network_interceptor.AuthAlreadyHandledException(data)

  raised when an auth challenge has already been handled by an external application (for example chrome-extension)

  property request: InterceptedAuth

    the corresponding auth challenge

class selenium_driverless.scripts.network_interceptor.RequestDoneException(data)

  raised when the request or auth challenge has already been resumed

  property request: InterceptedRequest | InterceptedAuth

    the corresponding request or auth challenge