pydoll-python 1.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pydoll/__init__.py +0 -0
- pydoll/browser/__init__.py +0 -0
- pydoll/browser/base.py +524 -0
- pydoll/browser/chrome.py +31 -0
- pydoll/browser/managers.py +154 -0
- pydoll/browser/options.py +62 -0
- pydoll/browser/page.py +433 -0
- pydoll/commands/__init__.py +18 -0
- pydoll/commands/browser.py +108 -0
- pydoll/commands/dom.py +212 -0
- pydoll/commands/fetch.py +308 -0
- pydoll/commands/input.py +106 -0
- pydoll/commands/network.py +334 -0
- pydoll/commands/page.py +187 -0
- pydoll/commands/runtime.py +45 -0
- pydoll/commands/storage.py +18 -0
- pydoll/commands/target.py +35 -0
- pydoll/connection/__init__.py +0 -0
- pydoll/connection/connection.py +232 -0
- pydoll/connection/managers.py +136 -0
- pydoll/constants.py +125 -0
- pydoll/element.py +313 -0
- pydoll/events/__init__.py +13 -0
- pydoll/events/browser.py +26 -0
- pydoll/events/dom.py +108 -0
- pydoll/events/fetch.py +29 -0
- pydoll/events/network.py +160 -0
- pydoll/events/page.py +144 -0
- pydoll/exceptions.py +82 -0
- pydoll/mixins/__init__.py +0 -0
- pydoll/mixins/find_elements.py +180 -0
- pydoll/utils.py +50 -0
- pydoll_python-1.2.0.dist-info/LICENSE +9 -0
- pydoll_python-1.2.0.dist-info/METADATA +200 -0
- pydoll_python-1.2.0.dist-info/RECORD +36 -0
- pydoll_python-1.2.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
class BrowserCommands:
|
|
2
|
+
"""
|
|
3
|
+
BrowserCommands class provides a set of commands to interact with the
|
|
4
|
+
browser's main functionality based on CDP. These commands allow for
|
|
5
|
+
managing browser windows, such as closing windows, retrieving window IDs,
|
|
6
|
+
and adjusting window bounds (size and state).
|
|
7
|
+
|
|
8
|
+
The following operations can be performed:
|
|
9
|
+
- Close the browser.
|
|
10
|
+
- Get the ID of the current window.
|
|
11
|
+
- Set the size and position of a specific window.
|
|
12
|
+
- Maximize or minimize a specific window.
|
|
13
|
+
|
|
14
|
+
Each method generates a command that can be sent to the browser
|
|
15
|
+
as part of the communication with the browser's underlying API.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
CLOSE = {'method': 'Browser.close'}
|
|
19
|
+
GET_WINDOW_ID = {'method': 'Browser.WindowID'}
|
|
20
|
+
SET_WINDOW_BOUNDS_TEMPLATE = {
|
|
21
|
+
'method': 'Browser.setWindowBounds',
|
|
22
|
+
'params': {},
|
|
23
|
+
}
|
|
24
|
+
SET_DOWNLOAD_BEHAVIOR = {
|
|
25
|
+
'method': 'Browser.setDownloadBehavior',
|
|
26
|
+
'params': {},
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@classmethod
|
|
30
|
+
def set_download_path(cls, path: str) -> dict:
|
|
31
|
+
"""
|
|
32
|
+
Generates the command to set the download path for the browser.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
path (str): The path to set for downloads.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
dict: The command to be sent to the browser.
|
|
39
|
+
"""
|
|
40
|
+
command = cls.SET_DOWNLOAD_BEHAVIOR.copy()
|
|
41
|
+
command['params']['behavior'] = 'allow'
|
|
42
|
+
command['params']['downloadPath'] = path
|
|
43
|
+
return command
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def close(cls) -> dict:
|
|
47
|
+
"""
|
|
48
|
+
Generates the command to close the browser.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
dict: The command to be sent to the browser.
|
|
52
|
+
"""
|
|
53
|
+
return cls.CLOSE
|
|
54
|
+
|
|
55
|
+
@classmethod
|
|
56
|
+
def get_window_id(cls) -> dict:
|
|
57
|
+
"""
|
|
58
|
+
Generates the command to get the ID of the current window.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
dict: The command to be sent to the browser.
|
|
62
|
+
"""
|
|
63
|
+
return cls.GET_WINDOW_ID
|
|
64
|
+
|
|
65
|
+
@classmethod
|
|
66
|
+
def set_window_bounds(cls, window_id: int, bounds: dict) -> dict:
|
|
67
|
+
"""
|
|
68
|
+
Generates the command to set the bounds of a window.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
window_id (int): The ID of the window to set the bounds for.
|
|
72
|
+
bounds (dict): The bounds to set for the window,
|
|
73
|
+
which should include width, height,
|
|
74
|
+
and optionally x and y coordinates.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
dict: The command to be sent to the browser.
|
|
78
|
+
"""
|
|
79
|
+
command = cls.SET_WINDOW_BOUNDS_TEMPLATE.copy()
|
|
80
|
+
command['params']['windowId'] = window_id
|
|
81
|
+
command['params']['bounds'] = bounds
|
|
82
|
+
return command
|
|
83
|
+
|
|
84
|
+
@classmethod
|
|
85
|
+
def set_window_maximized(cls, window_id: int) -> dict:
|
|
86
|
+
"""
|
|
87
|
+
Generates the command to maximize a window.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
window_id (int): The ID of the window to maximize.
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
dict: The command to be sent to the browser.
|
|
94
|
+
"""
|
|
95
|
+
return cls.set_window_bounds(window_id, {'windowState': 'maximized'})
|
|
96
|
+
|
|
97
|
+
@classmethod
|
|
98
|
+
def set_window_minimized(cls, window_id: int) -> dict:
|
|
99
|
+
"""
|
|
100
|
+
Generates the command to minimize a window.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
window_id (int): The ID of the window to minimize.
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
dict: The command to be sent to the browser.
|
|
107
|
+
"""
|
|
108
|
+
return cls.set_window_bounds(window_id, {'windowState': 'minimized'})
|
pydoll/commands/dom.py
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
from typing import Literal
|
|
3
|
+
|
|
4
|
+
from pydoll.commands.runtime import RuntimeCommands
|
|
5
|
+
from pydoll.constants import By, Scripts
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class DomCommands:
|
|
9
|
+
"""
|
|
10
|
+
A class to define commands for interacting with the Document
|
|
11
|
+
Object Model (DOM) using the Chrome DevTools Protocol (CDP).
|
|
12
|
+
The commands allow for various operations on DOM nodes,
|
|
13
|
+
such as enabling the DOM domain, retrieving the
|
|
14
|
+
DOM document, describing nodes, and querying elements.
|
|
15
|
+
|
|
16
|
+
Attributes:
|
|
17
|
+
SelectorType (Literal): A type definition for supported selector types.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
SelectorType = Literal[
|
|
21
|
+
By.CSS_SELECTOR, By.XPATH, By.CLASS_NAME, By.ID, By.TAG_NAME
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
ENABLE = {'method': 'DOM.enable'}
|
|
25
|
+
DOM_DOCUMENT = {'method': 'DOM.getDocument'}
|
|
26
|
+
DESCRIBE_NODE_TEMPLATE = {'method': 'DOM.describeNode', 'params': {}}
|
|
27
|
+
FIND_ELEMENT_TEMPLATE = {'method': 'DOM.querySelector', 'params': {}}
|
|
28
|
+
FIND_ALL_ELEMENTS_TEMPLATE = {
|
|
29
|
+
'method': 'DOM.querySelectorAll',
|
|
30
|
+
'params': {},
|
|
31
|
+
}
|
|
32
|
+
BOX_MODEL_TEMPLATE = {'method': 'DOM.getBoxModel', 'params': {}}
|
|
33
|
+
RESOLVE_NODE_TEMPLATE = {'method': 'DOM.resolveNode', 'params': {}}
|
|
34
|
+
REQUEST_NODE_TEMPLATE = {'method': 'DOM.requestNode', 'params': {}}
|
|
35
|
+
GET_OUTER_HTML = {
|
|
36
|
+
'method': 'DOM.getOuterHTML',
|
|
37
|
+
'params': {},
|
|
38
|
+
}
|
|
39
|
+
SCROLL_INTO_VIEW_IF_NEEDED = {
|
|
40
|
+
'method': 'DOM.scrollIntoViewIfNeeded',
|
|
41
|
+
'params': {},
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@classmethod
|
|
45
|
+
def scroll_into_view(cls, object_id: str) -> dict:
|
|
46
|
+
"""Generates the command to scroll a specific DOM node into view."""
|
|
47
|
+
command = copy.deepcopy(cls.SCROLL_INTO_VIEW_IF_NEEDED)
|
|
48
|
+
command['params']['objectId'] = object_id
|
|
49
|
+
return command
|
|
50
|
+
|
|
51
|
+
@classmethod
|
|
52
|
+
def get_outer_html(cls, object_id: int) -> dict:
|
|
53
|
+
"""Generates the command to get the outer HTML"""
|
|
54
|
+
command = copy.deepcopy(cls.GET_OUTER_HTML)
|
|
55
|
+
command['params']['objectId'] = object_id
|
|
56
|
+
return command
|
|
57
|
+
|
|
58
|
+
@classmethod
|
|
59
|
+
def dom_document(cls) -> dict:
|
|
60
|
+
"""
|
|
61
|
+
Generates the command to get the root DOM node of the current page.
|
|
62
|
+
"""
|
|
63
|
+
return cls.DOM_DOCUMENT
|
|
64
|
+
|
|
65
|
+
@classmethod
|
|
66
|
+
def request_node(cls, object_id: str) -> dict:
|
|
67
|
+
"""Generates the command to request a specific DOM node by its object
|
|
68
|
+
ID."""
|
|
69
|
+
command = copy.deepcopy(cls.REQUEST_NODE_TEMPLATE)
|
|
70
|
+
command['params']['objectId'] = object_id
|
|
71
|
+
return command
|
|
72
|
+
|
|
73
|
+
@classmethod
|
|
74
|
+
def describe_node(cls, object_id: str) -> dict:
|
|
75
|
+
"""Generates the command to describe a specific DOM node."""
|
|
76
|
+
command = copy.deepcopy(cls.DESCRIBE_NODE_TEMPLATE)
|
|
77
|
+
command['params']['objectId'] = object_id
|
|
78
|
+
return command
|
|
79
|
+
|
|
80
|
+
@classmethod
|
|
81
|
+
def box_model(cls, object_id: str) -> dict:
|
|
82
|
+
"""
|
|
83
|
+
Generates the command to get the box model of a specific DOM node.
|
|
84
|
+
"""
|
|
85
|
+
command = copy.deepcopy(cls.BOX_MODEL_TEMPLATE)
|
|
86
|
+
command['params']['objectId'] = object_id
|
|
87
|
+
return command
|
|
88
|
+
|
|
89
|
+
@classmethod
|
|
90
|
+
def enable_dom_events(cls) -> dict:
|
|
91
|
+
"""Generates the command to enable the DOM domain."""
|
|
92
|
+
return cls.ENABLE
|
|
93
|
+
|
|
94
|
+
@classmethod
|
|
95
|
+
def get_current_url(cls) -> dict:
|
|
96
|
+
"""Generates the command to get the current URL of the page."""
|
|
97
|
+
return RuntimeCommands.evaluate_script('window.location.href')
|
|
98
|
+
|
|
99
|
+
@classmethod
|
|
100
|
+
def find_element(
|
|
101
|
+
cls,
|
|
102
|
+
by: SelectorType,
|
|
103
|
+
value: str,
|
|
104
|
+
object_id: str = '',
|
|
105
|
+
) -> dict:
|
|
106
|
+
"""Generates a command to find a DOM element based on the specified
|
|
107
|
+
criteria."""
|
|
108
|
+
escaped_value = value.replace('"', '\\"')
|
|
109
|
+
match by:
|
|
110
|
+
case By.CLASS_NAME:
|
|
111
|
+
selector = f'.{escaped_value}'
|
|
112
|
+
case By.ID:
|
|
113
|
+
selector = f'#{escaped_value}'
|
|
114
|
+
case _:
|
|
115
|
+
selector = escaped_value
|
|
116
|
+
if object_id and not by == By.XPATH:
|
|
117
|
+
script = Scripts.RELATIVE_QUERY_SELECTOR.replace(
|
|
118
|
+
'{selector}', selector
|
|
119
|
+
)
|
|
120
|
+
command = RuntimeCommands.call_function_on(
|
|
121
|
+
object_id,
|
|
122
|
+
script,
|
|
123
|
+
return_by_value=False,
|
|
124
|
+
)
|
|
125
|
+
elif by == By.XPATH:
|
|
126
|
+
command = cls._find_element_by_xpath(value, object_id)
|
|
127
|
+
else:
|
|
128
|
+
command = RuntimeCommands.evaluate_script(
|
|
129
|
+
Scripts.QUERY_SELECTOR.replace('{selector}', selector)
|
|
130
|
+
)
|
|
131
|
+
return command
|
|
132
|
+
|
|
133
|
+
@classmethod
|
|
134
|
+
def find_elements(
|
|
135
|
+
cls,
|
|
136
|
+
by: SelectorType,
|
|
137
|
+
value: str,
|
|
138
|
+
object_id: str = '',
|
|
139
|
+
) -> dict:
|
|
140
|
+
"""Generates a command to find multiple DOM elements based on the
|
|
141
|
+
specified criteria."""
|
|
142
|
+
escaped_value = value.replace('"', '\\"')
|
|
143
|
+
match by:
|
|
144
|
+
case By.CLASS_NAME:
|
|
145
|
+
selector = f'.{escaped_value}'
|
|
146
|
+
case By.ID:
|
|
147
|
+
selector = f'#{escaped_value}'
|
|
148
|
+
case _:
|
|
149
|
+
selector = escaped_value
|
|
150
|
+
if object_id and not by == By.XPATH:
|
|
151
|
+
script = Scripts.RELATIVE_QUERY_SELECTOR_ALL.replace(
|
|
152
|
+
'{selector}', escaped_value
|
|
153
|
+
)
|
|
154
|
+
command = RuntimeCommands.call_function_on(
|
|
155
|
+
object_id,
|
|
156
|
+
script,
|
|
157
|
+
return_by_value=False,
|
|
158
|
+
)
|
|
159
|
+
elif by == By.XPATH:
|
|
160
|
+
command = cls._find_elements_by_xpath(value, object_id)
|
|
161
|
+
else:
|
|
162
|
+
command = RuntimeCommands.evaluate_script(
|
|
163
|
+
Scripts.QUERY_SELECTOR_ALL.replace('{selector}', selector)
|
|
164
|
+
)
|
|
165
|
+
return command
|
|
166
|
+
|
|
167
|
+
@classmethod
|
|
168
|
+
def _find_element_by_xpath(cls, xpath: str, object_id: str) -> dict:
|
|
169
|
+
"""Creates a command to find a DOM element by XPath."""
|
|
170
|
+
escaped_value = xpath.replace('"', '\\"')
|
|
171
|
+
if object_id:
|
|
172
|
+
escaped_value = cls._ensure_relative_xpath(escaped_value)
|
|
173
|
+
script = Scripts.FIND_RELATIVE_XPATH_ELEMENT.replace(
|
|
174
|
+
'{escaped_value}', escaped_value
|
|
175
|
+
)
|
|
176
|
+
command = RuntimeCommands.call_function_on(
|
|
177
|
+
object_id,
|
|
178
|
+
script,
|
|
179
|
+
return_by_value=False,
|
|
180
|
+
)
|
|
181
|
+
else:
|
|
182
|
+
script = Scripts.FIND_XPATH_ELEMENT.replace(
|
|
183
|
+
'{escaped_value}', escaped_value
|
|
184
|
+
)
|
|
185
|
+
command = RuntimeCommands.evaluate_script(script)
|
|
186
|
+
return command
|
|
187
|
+
|
|
188
|
+
@classmethod
|
|
189
|
+
def _find_elements_by_xpath(cls, xpath: str, object_id: str) -> dict:
|
|
190
|
+
"""Creates a command to find multiple DOM elements by XPath."""
|
|
191
|
+
escaped_value = xpath.replace('"', '\\"')
|
|
192
|
+
if object_id:
|
|
193
|
+
escaped_value = cls._ensure_relative_xpath(escaped_value)
|
|
194
|
+
script = Scripts.FIND_RELATIVE_XPATH_ELEMENTS.replace(
|
|
195
|
+
'{escaped_value}', escaped_value
|
|
196
|
+
)
|
|
197
|
+
command = RuntimeCommands.call_function_on(
|
|
198
|
+
object_id,
|
|
199
|
+
script,
|
|
200
|
+
return_by_value=False,
|
|
201
|
+
)
|
|
202
|
+
else:
|
|
203
|
+
script = Scripts.FIND_XPATH_ELEMENTS.replace(
|
|
204
|
+
'{escaped_value}', escaped_value
|
|
205
|
+
)
|
|
206
|
+
command = RuntimeCommands.evaluate_script(script)
|
|
207
|
+
return command
|
|
208
|
+
|
|
209
|
+
@staticmethod
|
|
210
|
+
def _ensure_relative_xpath(xpath: str) -> str:
|
|
211
|
+
"""Ensures that the XPath expression is relative."""
|
|
212
|
+
return f'.{xpath}' if not xpath.startswith('.') else xpath
|
pydoll/commands/fetch.py
ADDED
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
class FetchCommands:
|
|
2
|
+
"""
|
|
3
|
+
A collection of command templates for handling fetch events in the browser.
|
|
4
|
+
|
|
5
|
+
This class provides a structured way to create and manage commands related
|
|
6
|
+
to fetch operations intercepted by the Fetch API. Each command corresponds
|
|
7
|
+
to specific actions that can be performed on fetch requests, such as
|
|
8
|
+
continuing a fetch request, fulfilling a fetch response, or handling
|
|
9
|
+
authentication challenges.
|
|
10
|
+
|
|
11
|
+
Attributes:
|
|
12
|
+
CONTINUE_REQUEST (dict): Template for continuing an intercepted fetch
|
|
13
|
+
request.
|
|
14
|
+
CONTINUE_REQUEST_WITH_AUTH (dict): Template for continuing a fetch
|
|
15
|
+
request that requires authentication.
|
|
16
|
+
DISABLE (dict): Template for disabling fetch interception.
|
|
17
|
+
ENABLE (dict): Template for enabling fetch interception.
|
|
18
|
+
FAIL_REQUEST (dict): Template for simulating a failure in a fetch
|
|
19
|
+
request.
|
|
20
|
+
FULFILL_REQUEST (dict): Template for fulfilling a fetch request with
|
|
21
|
+
custom responses.
|
|
22
|
+
GET_RESPONSE_BODY (dict): Template for retrieving the response body of
|
|
23
|
+
a fetch request.
|
|
24
|
+
CONTINUE_RESPONSE (dict): Template for continuing a fetch response for
|
|
25
|
+
an intercepted request.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
CONTINUE_REQUEST = {'method': 'Fetch.continueRequest', 'params': {}}
|
|
29
|
+
CONTINUE_REQUEST_WITH_AUTH = {
|
|
30
|
+
'method': 'Fetch.continueWithAuth',
|
|
31
|
+
'params': {},
|
|
32
|
+
}
|
|
33
|
+
DISABLE = {'method': 'Fetch.disable', 'params': {}}
|
|
34
|
+
ENABLE = {'method': 'Fetch.enable', 'params': {}}
|
|
35
|
+
FAIL_REQUEST = {'method': 'Fetch.failRequest', 'params': {}}
|
|
36
|
+
FULFILL_REQUEST = {'method': 'Fetch.fulfillRequest', 'params': {}}
|
|
37
|
+
GET_RESPONSE_BODY = {'method': 'Fetch.getResponseBody', 'params': {}}
|
|
38
|
+
CONTINUE_RESPONSE = {'method': 'Fetch.continueResponse', 'params': {}}
|
|
39
|
+
|
|
40
|
+
@classmethod
|
|
41
|
+
def continue_request( # noqa: PLR0913, PLR0917
|
|
42
|
+
cls,
|
|
43
|
+
request_id: str,
|
|
44
|
+
url: str = '',
|
|
45
|
+
method: str = '',
|
|
46
|
+
post_data: str = '',
|
|
47
|
+
headers: dict = {},
|
|
48
|
+
intercept_response: bool = False,
|
|
49
|
+
):
|
|
50
|
+
"""
|
|
51
|
+
Creates a command to continue a paused fetch request.
|
|
52
|
+
|
|
53
|
+
This command allows the browser to resume a fetch operation that has
|
|
54
|
+
been intercepted. You can modify the fetch request URL, method,
|
|
55
|
+
headers, and body before continuing.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
request_id (str): The ID of the fetch request to continue.
|
|
59
|
+
url (str, optional): The new URL for the fetch request. Defaults to
|
|
60
|
+
''.
|
|
61
|
+
method (str, optional): The HTTP method to use (e.g., 'GET',
|
|
62
|
+
'POST'). Defaults to ''.
|
|
63
|
+
postData (str, optional): The body data to send with the fetch
|
|
64
|
+
request. Defaults to ''.
|
|
65
|
+
headers (dict, optional): A dictionary of HTTP headers to include
|
|
66
|
+
in the fetch request. Defaults to {}.
|
|
67
|
+
interceptResponse (bool, optional): Indicates if the response
|
|
68
|
+
should be intercepted. Defaults to False.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
dict: A command template for continuing the fetch request.
|
|
72
|
+
"""
|
|
73
|
+
continue_request_template = cls.CONTINUE_REQUEST.copy()
|
|
74
|
+
continue_request_template['params']['requestId'] = request_id
|
|
75
|
+
if url:
|
|
76
|
+
continue_request_template['params']['url'] = url
|
|
77
|
+
if method:
|
|
78
|
+
continue_request_template['params']['method'] = method
|
|
79
|
+
if post_data:
|
|
80
|
+
continue_request_template['params']['postData'] = post_data
|
|
81
|
+
if headers:
|
|
82
|
+
continue_request_template['params']['headers'] = headers
|
|
83
|
+
if intercept_response:
|
|
84
|
+
continue_request_template['params']['interceptResponse'] = (
|
|
85
|
+
intercept_response
|
|
86
|
+
)
|
|
87
|
+
return continue_request_template
|
|
88
|
+
|
|
89
|
+
@classmethod
|
|
90
|
+
def continue_request_with_auth(
|
|
91
|
+
cls, request_id: str, proxy_username: str, proxy_password: str
|
|
92
|
+
):
|
|
93
|
+
"""
|
|
94
|
+
Creates a command to continue a paused fetch request with
|
|
95
|
+
authentication.
|
|
96
|
+
|
|
97
|
+
This command is used when the fetch operation requires authentication.
|
|
98
|
+
It provides the necessary credentials to continue the request.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
request_id (str): The ID of the fetch request to continue.
|
|
102
|
+
proxy_username (str): The username for proxy authentication.
|
|
103
|
+
proxy_password (str): The password for proxy authentication.
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
dict: A command template for continuing the fetch request with
|
|
107
|
+
authentication.
|
|
108
|
+
"""
|
|
109
|
+
continue_request_with_auth_template = (
|
|
110
|
+
cls.CONTINUE_REQUEST_WITH_AUTH.copy()
|
|
111
|
+
)
|
|
112
|
+
continue_request_with_auth_template['params']['requestId'] = request_id
|
|
113
|
+
continue_request_with_auth_template['params'][
|
|
114
|
+
'authChallengeResponse'
|
|
115
|
+
] = {
|
|
116
|
+
'response': 'ProvideCredentials',
|
|
117
|
+
'username': proxy_username,
|
|
118
|
+
'password': proxy_password,
|
|
119
|
+
}
|
|
120
|
+
return continue_request_with_auth_template
|
|
121
|
+
|
|
122
|
+
@classmethod
|
|
123
|
+
def disable_fetch_events(cls):
|
|
124
|
+
"""
|
|
125
|
+
Creates a command to disable fetch interception.
|
|
126
|
+
|
|
127
|
+
This command stops the browser from intercepting fetch requests.
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
dict: A command template for disabling fetch interception.
|
|
131
|
+
"""
|
|
132
|
+
return cls.DISABLE
|
|
133
|
+
|
|
134
|
+
@classmethod
|
|
135
|
+
def enable_fetch_events(
|
|
136
|
+
cls, handle_auth_requests: bool, resource_type: str
|
|
137
|
+
):
|
|
138
|
+
"""
|
|
139
|
+
Creates a command to enable fetch interception.
|
|
140
|
+
|
|
141
|
+
This command allows the browser to start intercepting fetch requests.
|
|
142
|
+
You can specify whether to handle authentication challenges and the
|
|
143
|
+
types of resources to intercept.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
handle_auth_requests (bool): Indicates if authentication requests
|
|
147
|
+
should be handled.
|
|
148
|
+
resource_type (str): The type of resource to intercept (e.g.,
|
|
149
|
+
'Document', 'Image').
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
dict: A command template for enabling fetch interception.
|
|
153
|
+
"""
|
|
154
|
+
enable_fetch_events_template = cls.ENABLE.copy()
|
|
155
|
+
enable_fetch_events_template['params']['patterns'] = [
|
|
156
|
+
{'urlPattern': '*'}
|
|
157
|
+
]
|
|
158
|
+
if resource_type:
|
|
159
|
+
enable_fetch_events_template['params']['patterns'][0][
|
|
160
|
+
'resourceType'
|
|
161
|
+
] = resource_type
|
|
162
|
+
|
|
163
|
+
enable_fetch_events_template['params']['handleAuthRequests'] = (
|
|
164
|
+
handle_auth_requests
|
|
165
|
+
)
|
|
166
|
+
return enable_fetch_events_template
|
|
167
|
+
|
|
168
|
+
@classmethod
|
|
169
|
+
def fail_request(cls, request_id: str, error_reason: str):
|
|
170
|
+
"""
|
|
171
|
+
Creates a command to simulate a failure in a fetch request.
|
|
172
|
+
|
|
173
|
+
This command allows you to simulate a failure for a specific fetch
|
|
174
|
+
operation, providing a reason for the failure.
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
request_id (str): The ID of the fetch request to fail.
|
|
178
|
+
errorReason (str): A description of the failure reason.
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
dict: A command template for failing the fetch request.
|
|
182
|
+
"""
|
|
183
|
+
fail_request_template = cls.FAIL_REQUEST.copy()
|
|
184
|
+
fail_request_template['params']['requestId'] = request_id
|
|
185
|
+
fail_request_template['params']['errorReason'] = error_reason
|
|
186
|
+
return fail_request_template
|
|
187
|
+
|
|
188
|
+
@classmethod
|
|
189
|
+
def fulfill_request( # noqa: PLR0913, PLR0917
|
|
190
|
+
cls,
|
|
191
|
+
request_id: str,
|
|
192
|
+
response_code: int,
|
|
193
|
+
response_headers: dict = {},
|
|
194
|
+
binary_response_headers: str = '',
|
|
195
|
+
body: str = '',
|
|
196
|
+
response_phrase: str = '',
|
|
197
|
+
):
|
|
198
|
+
"""
|
|
199
|
+
Creates a command to fulfill a fetch request with a custom response.
|
|
200
|
+
|
|
201
|
+
This command allows you to provide a custom response for a fetch
|
|
202
|
+
operation, including the HTTP status code, headers, and body content.
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
request_id (str): The ID of the fetch request to fulfill.
|
|
206
|
+
responseCode (int): The HTTP status code to return.
|
|
207
|
+
responseHeaders (dict, optional): A dictionary of response headers.
|
|
208
|
+
Defaults to {}.
|
|
209
|
+
binaryResponseHeaders (str, optional): Binary response headers.
|
|
210
|
+
Defaults to ''.
|
|
211
|
+
body (str, optional): The body content of the response. Defaults to
|
|
212
|
+
''.
|
|
213
|
+
responsePhrase (str, optional): The response phrase (e.g., 'OK',
|
|
214
|
+
'Not Found'). Defaults to ''.
|
|
215
|
+
|
|
216
|
+
Returns:
|
|
217
|
+
dict: A command template for fulfilling the fetch request.
|
|
218
|
+
"""
|
|
219
|
+
fulfill_request_template = cls.FULFILL_REQUEST.copy()
|
|
220
|
+
fulfill_request_template['params']['requestId'] = request_id
|
|
221
|
+
if response_code:
|
|
222
|
+
fulfill_request_template['params']['responseCode'] = response_code
|
|
223
|
+
if response_headers:
|
|
224
|
+
fulfill_request_template['params']['responseHeaders'] = (
|
|
225
|
+
response_headers
|
|
226
|
+
)
|
|
227
|
+
if binary_response_headers:
|
|
228
|
+
fulfill_request_template['params']['binaryResponseHeaders'] = (
|
|
229
|
+
binary_response_headers
|
|
230
|
+
)
|
|
231
|
+
if body:
|
|
232
|
+
fulfill_request_template['params']['body'] = body
|
|
233
|
+
if response_phrase:
|
|
234
|
+
fulfill_request_template['params']['responsePhrase'] = (
|
|
235
|
+
response_phrase
|
|
236
|
+
)
|
|
237
|
+
return fulfill_request_template
|
|
238
|
+
|
|
239
|
+
@classmethod
|
|
240
|
+
def get_response_body(cls, request_id: str):
|
|
241
|
+
"""
|
|
242
|
+
Creates a command to retrieve the response body of a fetch request.
|
|
243
|
+
|
|
244
|
+
This command allows you to access the body of a completed fetch
|
|
245
|
+
operation, which can be useful for analyzing the response data.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
request_id (str): The ID of the fetch request to retrieve the body
|
|
249
|
+
from.
|
|
250
|
+
|
|
251
|
+
Returns:
|
|
252
|
+
dict: A command template for getting the response body.
|
|
253
|
+
"""
|
|
254
|
+
get_response_body_template = cls.GET_RESPONSE_BODY.copy()
|
|
255
|
+
get_response_body_template['params']['requestId'] = request_id
|
|
256
|
+
return get_response_body_template
|
|
257
|
+
|
|
258
|
+
@classmethod
|
|
259
|
+
def continue_response(
|
|
260
|
+
cls,
|
|
261
|
+
request_id: str,
|
|
262
|
+
response_code: int = '',
|
|
263
|
+
response_headers: dict = {},
|
|
264
|
+
binary_response_headers: str = '',
|
|
265
|
+
response_phrase: str = '',
|
|
266
|
+
):
|
|
267
|
+
"""
|
|
268
|
+
Creates a command to continue a fetch response for an intercepted
|
|
269
|
+
request.
|
|
270
|
+
|
|
271
|
+
This command allows the browser to continue the response flow for a
|
|
272
|
+
specific fetch request, including customizing the HTTP status code,
|
|
273
|
+
headers, and response phrase.
|
|
274
|
+
|
|
275
|
+
Args:
|
|
276
|
+
requestId (str): The ID of the fetch request to continue the
|
|
277
|
+
response for.
|
|
278
|
+
responseCode (int, optional): The HTTP status code to send.
|
|
279
|
+
Defaults to ''.
|
|
280
|
+
responseHeaders (dict, optional): A dictionary of response headers.
|
|
281
|
+
Defaults to {}.
|
|
282
|
+
binaryResponseHeaders (str, optional): Binary response headers.
|
|
283
|
+
Defaults to ''.
|
|
284
|
+
responsePhrase (str, optional): The response phrase (e.g., 'OK').
|
|
285
|
+
Defaults to ''.
|
|
286
|
+
|
|
287
|
+
Returns:
|
|
288
|
+
dict: A command template for continuing the fetch response.
|
|
289
|
+
"""
|
|
290
|
+
continue_response_template = cls.CONTINUE_RESPONSE.copy()
|
|
291
|
+
continue_response_template['params']['requestId'] = request_id
|
|
292
|
+
if response_code:
|
|
293
|
+
continue_response_template['params']['responseCode'] = (
|
|
294
|
+
response_code
|
|
295
|
+
)
|
|
296
|
+
if response_headers:
|
|
297
|
+
continue_response_template['params']['responseHeaders'] = (
|
|
298
|
+
response_headers
|
|
299
|
+
)
|
|
300
|
+
if binary_response_headers:
|
|
301
|
+
continue_response_template['params']['binaryResponseHeaders'] = (
|
|
302
|
+
binary_response_headers
|
|
303
|
+
)
|
|
304
|
+
if response_phrase:
|
|
305
|
+
continue_response_template['params']['responsePhrase'] = (
|
|
306
|
+
response_phrase
|
|
307
|
+
)
|
|
308
|
+
return continue_response_template
|