CheeseAPI 2.0.8b5__tar.gz → 2.0.8b7__tar.gz
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.
- {cheeseapi-2.0.8b5 → cheeseapi-2.0.8b7}/CheeseAPI/request.py +1 -1
- {cheeseapi-2.0.8b5 → cheeseapi-2.0.8b7}/CheeseAPI/websocket.py +28 -9
- {cheeseapi-2.0.8b5 → cheeseapi-2.0.8b7}/PKG-INFO +2 -2
- {cheeseapi-2.0.8b5 → cheeseapi-2.0.8b7}/pyproject.toml +1 -1
- {cheeseapi-2.0.8b5 → cheeseapi-2.0.8b7}/.gitignore +0 -0
- {cheeseapi-2.0.8b5 → cheeseapi-2.0.8b7}/CheeseAPI/__init__.py +0 -0
- {cheeseapi-2.0.8b5 → cheeseapi-2.0.8b7}/CheeseAPI/app.py +0 -0
- {cheeseapi-2.0.8b5 → cheeseapi-2.0.8b7}/CheeseAPI/cors.py +0 -0
- {cheeseapi-2.0.8b5 → cheeseapi-2.0.8b7}/CheeseAPI/file.py +0 -0
- {cheeseapi-2.0.8b5 → cheeseapi-2.0.8b7}/CheeseAPI/printer.py +0 -0
- {cheeseapi-2.0.8b5 → cheeseapi-2.0.8b7}/CheeseAPI/response.py +0 -0
- {cheeseapi-2.0.8b5 → cheeseapi-2.0.8b7}/CheeseAPI/route.py +0 -0
- {cheeseapi-2.0.8b5 → cheeseapi-2.0.8b7}/CheeseAPI/scheduler.py +0 -0
- {cheeseapi-2.0.8b5 → cheeseapi-2.0.8b7}/CheeseAPI/signal.py +0 -0
- {cheeseapi-2.0.8b5 → cheeseapi-2.0.8b7}/CheeseAPI/static.py +0 -0
- {cheeseapi-2.0.8b5 → cheeseapi-2.0.8b7}/CheeseAPI/validator.py +0 -0
- {cheeseapi-2.0.8b5 → cheeseapi-2.0.8b7}/LICENSE +0 -0
- {cheeseapi-2.0.8b5 → cheeseapi-2.0.8b7}/README.md +0 -0
|
@@ -267,7 +267,7 @@ class RequestProxy:
|
|
|
267
267
|
name = None
|
|
268
268
|
filename = None
|
|
269
269
|
for line in headers.decode().strip().split('\r\n'):
|
|
270
|
-
if line.startswith('
|
|
270
|
+
if line.startswith('Content-Disposition:'):
|
|
271
271
|
name_match = re.search(r'name="([^"]*)"', line)
|
|
272
272
|
if name_match:
|
|
273
273
|
name = name_match.group(1)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import base64, hashlib, asyncio, ssl, struct, json
|
|
1
|
+
import base64, hashlib, asyncio, ssl, struct, json, inspect
|
|
2
2
|
from functools import partial
|
|
3
3
|
from typing import TYPE_CHECKING, AsyncIterable, Self
|
|
4
4
|
|
|
@@ -48,8 +48,8 @@ class Websocket:
|
|
|
48
48
|
self._request: 'Request' = request
|
|
49
49
|
|
|
50
50
|
self._proxy: 'WebsocketProxy' = request._proxy.app.WebsocketProxy_Class(request._proxy.app, self)
|
|
51
|
-
self._key: str = self.request.headers.get('sec-websocket-key')
|
|
52
|
-
subprotocols = self.request.headers.get('sec-websocket-protocol')
|
|
51
|
+
self._key: str = self.request.headers.get('sec-websocket-key') or self.request.headers.get('Sec-WebSocket-Key')
|
|
52
|
+
subprotocols = self.request.headers.get('sec-websocket-protocol') or self.request.headers.get('Sec-WebSocket-Protocol')
|
|
53
53
|
self._subprotocols: list[str] | None = subprotocols.strip().split(',') if subprotocols else None
|
|
54
54
|
self._subprotocol: str | None = None
|
|
55
55
|
self.response: Response | None = None
|
|
@@ -109,6 +109,8 @@ class Websocket:
|
|
|
109
109
|
close = DualMethod(_static_close, _instance_close)
|
|
110
110
|
|
|
111
111
|
class WebsocketProxy:
|
|
112
|
+
_sync_tasks: dict[str, asyncio.Task] = {}
|
|
113
|
+
|
|
112
114
|
@staticmethod
|
|
113
115
|
def _static_send(path: str, data: bytes | list | str | dict, *, websocket_key_or_keys: str | list[str] | None = None):
|
|
114
116
|
if static.websocket_sync_servers is not None:
|
|
@@ -223,19 +225,21 @@ class WebsocketProxy:
|
|
|
223
225
|
await self.message()
|
|
224
226
|
await self.disconnect()
|
|
225
227
|
except Exception as e:
|
|
226
|
-
|
|
228
|
+
result = self.app.printer.websocket_error(e, self.websocket)
|
|
229
|
+
if inspect.isawaitable(result):
|
|
230
|
+
await result
|
|
227
231
|
|
|
228
232
|
async def get_response(self) -> Response:
|
|
229
233
|
headers = {
|
|
230
|
-
'
|
|
231
|
-
'
|
|
232
|
-
'
|
|
234
|
+
'Upgrade': 'websocket',
|
|
235
|
+
'Connection': 'Upgrade',
|
|
236
|
+
'Sec-WebSocket-Accept': base64.b64encode(hashlib.sha1(f'{self.websocket.key}258EAFA5-E914-47DA-95CA-C5AB0DC85B11'.encode('utf-8')).digest()).decode('utf-8')
|
|
233
237
|
}
|
|
234
238
|
if self.websocket.subprotocols:
|
|
235
239
|
subprotocol = await self.websocket.on_subprotocol(self.websocket.subprotocols)
|
|
236
240
|
if subprotocol:
|
|
237
241
|
self.websocket._subprotocol = subprotocol
|
|
238
|
-
headers['
|
|
242
|
+
headers['Sec-WebSocket-Protocol'] = subprotocol
|
|
239
243
|
response = self.app.ResponseProxy_Class(self.app, Response(status = 101, headers = headers)).response
|
|
240
244
|
response._proxy.websocket = self.websocket
|
|
241
245
|
return response
|
|
@@ -244,7 +248,7 @@ class WebsocketProxy:
|
|
|
244
248
|
Websocket.connectors.setdefault(self.websocket.request.path, []).append(self.websocket)
|
|
245
249
|
if self.app.sync_server_url and self.websocket.request.path not in static.websocket_sync_server:
|
|
246
250
|
static.websocket_sync_server[self.websocket.request.path] = redis.asyncio.Redis.from_url(self.app.sync_server_url, socket_timeout = self.app.sync_server_timeout, socket_connect_timeout = self.app.sync_server_timeout)
|
|
247
|
-
asyncio.create_task(self.sync_server_running())
|
|
251
|
+
WebsocketProxy._sync_tasks[self.websocket.request.path] = asyncio.create_task(self.sync_server_running())
|
|
248
252
|
|
|
249
253
|
loop = asyncio.get_running_loop()
|
|
250
254
|
self.reader = asyncio.StreamReader()
|
|
@@ -259,10 +263,18 @@ class WebsocketProxy:
|
|
|
259
263
|
await self.websocket.on_connect()
|
|
260
264
|
|
|
261
265
|
async def sync_server_running(self):
|
|
266
|
+
pubsub = None
|
|
262
267
|
try:
|
|
263
268
|
if self.app.sync_server_url.startswith('redis'):
|
|
264
269
|
while True:
|
|
265
270
|
try:
|
|
271
|
+
if pubsub is not None:
|
|
272
|
+
try:
|
|
273
|
+
await pubsub.aclose()
|
|
274
|
+
except Exception:
|
|
275
|
+
pass
|
|
276
|
+
pubsub = None
|
|
277
|
+
|
|
266
278
|
pubsub = redis.asyncio.from_url(self.app.sync_server_url, socket_timeout = None, socket_connect_timeout = None).pubsub()
|
|
267
279
|
await pubsub.subscribe(self.websocket.request.path)
|
|
268
280
|
async for message in pubsub.listen():
|
|
@@ -302,6 +314,13 @@ class WebsocketProxy:
|
|
|
302
314
|
await asyncio.sleep(self.app.sync_server_timeout)
|
|
303
315
|
except (KeyboardInterrupt, SystemExit, asyncio.CancelledError):
|
|
304
316
|
...
|
|
317
|
+
finally:
|
|
318
|
+
WebsocketProxy._sync_tasks.pop(self.websocket.request.path, None)
|
|
319
|
+
if pubsub is not None:
|
|
320
|
+
try:
|
|
321
|
+
await pubsub.aclose()
|
|
322
|
+
except Exception:
|
|
323
|
+
pass
|
|
305
324
|
|
|
306
325
|
async def message(self):
|
|
307
326
|
while True:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|