17
17
import inspect
18
18
import json
19
19
import mimetypes
20
+ import sys
20
21
from collections import defaultdict
21
22
from pathlib import Path
22
23
from types import SimpleNamespace
31
32
Union ,
32
33
cast ,
33
34
)
35
+
36
+ if sys .version_info >= (3 , 8 ): # pragma: no cover
37
+ from typing import TypedDict
38
+ else : # pragma: no cover
39
+ from typing_extensions import TypedDict
34
40
from urllib import parse
35
41
36
42
from playwright ._impl ._api_structures import (
48
54
from_nullable_channel ,
49
55
)
50
56
from playwright ._impl ._event_context_manager import EventContextManagerImpl
51
- from playwright ._impl ._helper import FallbackOverrideParameters , locals_to_params
57
+ from playwright ._impl ._helper import locals_to_params
52
58
from playwright ._impl ._wait_helper import WaitHelper
53
59
54
60
if TYPE_CHECKING : # pragma: no cover
57
63
from playwright ._impl ._page import Page
58
64
59
65
66
+ class FallbackOverrideParameters (TypedDict , total = False ):
67
+ url : Optional [str ]
68
+ method : Optional [str ]
69
+ headers : Optional [Dict [str , str ]]
70
+ postData : Optional [Union [str , bytes ]]
71
+
72
+
73
+ class SerializedFallbackOverrides :
74
+ def __init__ (self ) -> None :
75
+ self .url : Optional [str ] = None
76
+ self .method : Optional [str ] = None
77
+ self .headers : Optional [Dict [str , str ]] = None
78
+ self .post_data_buffer : Optional [bytes ] = None
79
+
80
+
60
81
def serialize_headers (headers : Dict [str , str ]) -> HeadersArray :
61
82
return [
62
83
{"name" : name , "value" : value }
@@ -90,31 +111,47 @@ def __init__(
90
111
}
91
112
self ._provisional_headers = RawHeaders (self ._initializer ["headers" ])
92
113
self ._all_headers_future : Optional [asyncio .Future [RawHeaders ]] = None
93
- self ._fallback_overrides : FallbackOverrideParameters = (
94
- FallbackOverrideParameters ()
114
+ self ._fallback_overrides : SerializedFallbackOverrides = (
115
+ SerializedFallbackOverrides ()
95
116
)
117
+ base64_post_data = initializer .get ("postData" )
118
+ if base64_post_data is not None :
119
+ self ._fallback_overrides .post_data_buffer = base64 .b64decode (
120
+ base64_post_data
121
+ )
96
122
97
123
def __repr__ (self ) -> str :
98
124
return f"<Request url={ self .url !r} method={ self .method !r} >"
99
125
100
126
def _apply_fallback_overrides (self , overrides : FallbackOverrideParameters ) -> None :
101
- self ._fallback_overrides = cast (
102
- FallbackOverrideParameters , { ** self ._fallback_overrides , ** overrides }
127
+ self ._fallback_overrides . url = overrides . get (
128
+ "url" , self ._fallback_overrides . url
103
129
)
130
+ self ._fallback_overrides .method = overrides .get (
131
+ "method" , self ._fallback_overrides .method
132
+ )
133
+ self ._fallback_overrides .headers = overrides .get (
134
+ "headers" , self ._fallback_overrides .headers
135
+ )
136
+ post_data = overrides .get ("postData" )
137
+ if isinstance (post_data , str ):
138
+ self ._fallback_overrides .post_data_buffer = post_data .encode ()
139
+ elif isinstance (post_data , bytes ):
140
+ self ._fallback_overrides .post_data_buffer = post_data
141
+ elif post_data is not None :
142
+ self ._fallback_overrides .post_data_buffer = json .dumps (post_data ).encode ()
104
143
105
144
@property
106
145
def url (self ) -> str :
107
- return cast (str , self ._fallback_overrides .get ( " url" , self ._initializer ["url" ]) )
146
+ return cast (str , self ._fallback_overrides .url or self ._initializer ["url" ])
108
147
109
148
@property
110
149
def resource_type (self ) -> str :
111
150
return self ._initializer ["resourceType" ]
112
151
113
152
@property
114
153
def method (self ) -> str :
115
- return cast (
116
- str , self ._fallback_overrides .get ("method" , self ._initializer ["method" ])
117
- )
154
+ return cast (str , self ._fallback_overrides .method or self ._initializer ["method" ])
118
155
119
156
async def sizes (self ) -> RequestSizes :
120
157
response = await self .response ()
@@ -124,7 +161,7 @@ async def sizes(self) -> RequestSizes:
124
161
125
162
@property
126
163
def post_data (self ) -> Optional [str ]:
127
- data = self ._fallback_overrides .get ( "postData" , self . post_data_buffer )
164
+ data = self ._fallback_overrides .post_data_buffer
128
165
if not data :
129
166
return None
130
167
return data .decode () if isinstance (data , bytes ) else data
@@ -144,17 +181,7 @@ def post_data_json(self) -> Optional[Any]:
144
181
145
182
@property
146
183
def post_data_buffer (self ) -> Optional [bytes ]:
147
- override = self ._fallback_overrides .get ("post_data" )
148
- if override :
149
- return (
150
- override .encode ()
151
- if isinstance (override , str )
152
- else cast (bytes , override )
153
- )
154
- b64_content = self ._initializer .get ("postData" )
155
- if b64_content is None :
156
- return None
157
- return base64 .b64decode (b64_content )
184
+ return self ._fallback_overrides .post_data_buffer
158
185
159
186
async def response (self ) -> Optional ["Response" ]:
160
187
return from_nullable_channel (await self ._channel .send ("response" ))
@@ -189,7 +216,7 @@ def _set_response_end_timing(self, response_end_timing: float) -> None:
189
216
190
217
@property
191
218
def headers (self ) -> Headers :
192
- override = self ._fallback_overrides .get ( " headers" )
219
+ override = self ._fallback_overrides .headers
193
220
if override :
194
221
return RawHeaders ._from_headers_dict_lossy (override ).headers ()
195
222
return self ._provisional_headers .headers ()
@@ -204,7 +231,7 @@ async def header_value(self, name: str) -> Optional[str]:
204
231
return (await self ._actual_headers ()).get (name )
205
232
206
233
async def _actual_headers (self ) -> "RawHeaders" :
207
- override = self ._fallback_overrides .get ( " headers" )
234
+ override = self ._fallback_overrides .headers
208
235
if override :
209
236
return RawHeaders (serialize_headers (override ))
210
237
if not self ._all_headers_future :
@@ -254,6 +281,7 @@ async def fulfill(
254
281
status : int = None ,
255
282
headers : Dict [str , str ] = None ,
256
283
body : Union [str , bytes ] = None ,
284
+ json : Any = None ,
257
285
path : Union [str , Path ] = None ,
258
286
contentType : str = None ,
259
287
response : "APIResponse" = None ,
@@ -270,6 +298,8 @@ async def fulfill(
270
298
)
271
299
from playwright ._impl ._fetch import APIResponse
272
300
301
+ if json is not None :
302
+ body = json .dumps (json )
273
303
if body is None and path is None and isinstance (response , APIResponse ):
274
304
if response ._request ._connection is self ._connection :
275
305
params ["fetchResponseUid" ] = response ._fetch_uid
@@ -295,6 +325,8 @@ async def fulfill(
295
325
headers = {k .lower (): str (v ) for k , v in params .get ("headers" , {}).items ()}
296
326
if params .get ("contentType" ):
297
327
headers ["content-type" ] = params ["contentType" ]
328
+ elif json :
329
+ headers ["content-type" ] = "application/json"
298
330
elif path :
299
331
headers ["content-type" ] = (
300
332
mimetypes .guess_type (str (Path (path )))[0 ] or "application/octet-stream"
@@ -305,12 +337,24 @@ async def fulfill(
305
337
await self ._race_with_page_close (self ._channel .send ("fulfill" , params ))
306
338
self ._report_handled (True )
307
339
340
+ async def fetch (
341
+ self ,
342
+ url : str = None ,
343
+ method : str = None ,
344
+ headers : Dict [str , str ] = None ,
345
+ postData : Union [Any , str , bytes ] = None ,
346
+ ) -> "APIResponse" :
347
+ page = self .request .frame ._page
348
+ return await page .context .request ._inner_fetch (
349
+ self .request , url , method , headers , postData
350
+ )
351
+
308
352
async def fallback (
309
353
self ,
310
354
url : str = None ,
311
355
method : str = None ,
312
356
headers : Dict [str , str ] = None ,
313
- postData : Union [str , bytes ] = None ,
357
+ postData : Union [Any , str , bytes ] = None ,
314
358
) -> None :
315
359
overrides = cast (FallbackOverrideParameters , locals_to_params (locals ()))
316
360
self ._check_not_handled ()
@@ -322,7 +366,7 @@ async def continue_(
322
366
url : str = None ,
323
367
method : str = None ,
324
368
headers : Dict [str , str ] = None ,
325
- postData : Union [str , bytes ] = None ,
369
+ postData : Union [Any , str , bytes ] = None ,
326
370
) -> None :
327
371
overrides = cast (FallbackOverrideParameters , locals_to_params (locals ()))
328
372
self ._check_not_handled ()
@@ -335,23 +379,18 @@ def _internal_continue(
335
379
) -> Coroutine [Any , Any , None ]:
336
380
async def continue_route () -> None :
337
381
try :
338
- post_data_for_wire : Optional [str ] = None
339
- post_data_from_overrides = self .request ._fallback_overrides .get (
340
- "postData"
341
- )
342
- if post_data_from_overrides is not None :
343
- post_data_for_wire = (
344
- base64 .b64encode (post_data_from_overrides .encode ()).decode ()
345
- if isinstance (post_data_from_overrides , str )
346
- else base64 .b64encode (post_data_from_overrides ).decode ()
347
- )
348
- params = locals_to_params (
349
- cast (Dict [str , str ], self .request ._fallback_overrides )
350
- )
382
+ params : Dict [str , Any ] = {}
383
+ params ["url" ] = self .request ._fallback_overrides .url
384
+ params ["method" ] = self .request ._fallback_overrides .method
385
+ params ["headers" ] = self .request ._fallback_overrides .headers
386
+ if self .request ._fallback_overrides .post_data_buffer is not None :
387
+ params ["postData" ] = base64 .b64encode (
388
+ self .request ._fallback_overrides .post_data_buffer
389
+ ).decode ()
390
+ params = locals_to_params (params )
391
+
351
392
if "headers" in params :
352
393
params ["headers" ] = serialize_headers (params ["headers" ])
353
- if post_data_for_wire is not None :
354
- params ["postData" ] = post_data_for_wire
355
394
await self ._connection .wrap_api_call (
356
395
lambda : self ._race_with_page_close (
357
396
self ._channel .send (
0 commit comments