python-engineio 4.14.0__py3-none-any.whl → 4.15.1__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.
engineio/async_client.py CHANGED
@@ -226,6 +226,7 @@ class AsyncClient(base_client.BaseClient):
226
226
  if not self.external_http: # pragma: no cover
227
227
  if self.http and not self.http.closed:
228
228
  await self.http.close()
229
+ self.http = None
229
230
 
230
231
  def __del__(self): # pragma: no cover
231
232
  # try to close the aiohttp session if it is still open
@@ -323,8 +324,13 @@ class AsyncClient(base_client.BaseClient):
323
324
  self.logger.info(
324
325
  'Attempting WebSocket connection to ' + websocket_url)
325
326
 
326
- if self.http is None or self.http.closed: # pragma: no cover
327
- self.http = aiohttp.ClientSession()
327
+ if self.http is None or self.http.closed:
328
+ if self.http_factory:
329
+ self.http = self.http_factory()
330
+ if inspect.iscoroutine(self.http):
331
+ self.http = await self.http
332
+ else:
333
+ self.http = aiohttp.ClientSession()
328
334
 
329
335
  # extract any new cookies passed in a header so that they can also be
330
336
  # sent the the WebSocket route
@@ -458,12 +464,17 @@ class AsyncClient(base_client.BaseClient):
458
464
 
459
465
  async def _send_request(
460
466
  self, method, url, headers=None, body=None,
461
- timeout=None): # pragma: no cover
467
+ timeout=None):
462
468
  if self.http is None or self.http.closed:
463
- self.http = aiohttp.ClientSession()
469
+ if self.http_factory:
470
+ self.http = self.http_factory()
471
+ if inspect.iscoroutine(self.http):
472
+ self.http = await self.http
473
+ else:
474
+ self.http = aiohttp.ClientSession()
464
475
  http_method = getattr(self.http, method.lower())
465
476
 
466
- try:
477
+ try: # pragma: no cover
467
478
  if not self.ssl_verify:
468
479
  return await http_method(
469
480
  url, headers=headers, data=body,
@@ -473,7 +484,8 @@ class AsyncClient(base_client.BaseClient):
473
484
  url, headers=headers, data=body,
474
485
  timeout=aiohttp.ClientTimeout(total=timeout))
475
486
 
476
- except (aiohttp.ClientError, asyncio.TimeoutError) as exc:
487
+ except (aiohttp.ClientError, asyncio.TimeoutError) \
488
+ as exc: # pragma: no cover
477
489
  self.logger.info('HTTP %s request to %s failed with error %s.',
478
490
  method, url, exc)
479
491
  return str(exc)
engineio/async_server.py CHANGED
@@ -298,7 +298,19 @@ class AsyncServer(base_server.BaseServer):
298
298
  self._log_error_once(f'{e} {sid}', 'bad-sid')
299
299
  r = self._bad_request(f'{e} {sid}')
300
300
  else:
301
- if self.transport(sid) != transport and \
301
+ if not socket.connected:
302
+ # cannot accept requests before connecting
303
+ self._log_error_once(
304
+ f'Socket for session {sid} is not connected',
305
+ 'not-connected')
306
+ r = self._bad_request('Not connected')
307
+ elif socket.upgraded:
308
+ # cannot accept HTTP requests once upgraded
309
+ self._log_error_once(
310
+ f'Unexpected HTTP request for session {sid}',
311
+ 'unexpected-http')
312
+ r = self._bad_request('Unexpected HTTP request')
313
+ elif transport != 'polling' and \
302
314
  transport != upgrade_header:
303
315
  self._log_error_once(
304
316
  f'Invalid transport for session {sid}',
@@ -326,18 +338,31 @@ class AsyncServer(base_server.BaseServer):
326
338
  r = self._bad_request(f'Invalid session {sid}')
327
339
  else:
328
340
  socket = self._get_socket(sid)
329
- try:
330
- await socket.handle_post_request(environ)
331
- r = self._ok(jsonp_index=jsonp_index)
332
- except exceptions.EngineIOError:
333
- if sid in self.sockets: # pragma: no cover
334
- await self.disconnect(sid)
335
- r = self._bad_request()
336
- except: # pragma: no cover
337
- # for any other unexpected errors, we log the error
338
- # and keep going
339
- self.logger.exception('post request handler error')
340
- r = self._ok(jsonp_index=jsonp_index)
341
+ if not socket.connected:
342
+ # cannot accept requests before connecting
343
+ self._log_error_once(
344
+ f'Socket for session {sid} is not connected',
345
+ 'not-connected')
346
+ r = self._bad_request('Not connected')
347
+ elif not socket.upgraded:
348
+ try:
349
+ await socket.handle_post_request(environ)
350
+ r = self._ok(jsonp_index=jsonp_index)
351
+ except exceptions.EngineIOError:
352
+ if sid in self.sockets: # pragma: no cover
353
+ await self.disconnect(sid)
354
+ r = self._bad_request()
355
+ except: # pragma: no cover
356
+ # for any other unexpected errors, we log the error
357
+ # and keep going
358
+ self.logger.exception('post request handler error')
359
+ r = self._ok(jsonp_index=jsonp_index)
360
+ else:
361
+ # cannot accept HTTP requests once upgraded
362
+ self._log_error_once(
363
+ f'Unexpected HTTP request for session {sid}',
364
+ 'unexpected-http')
365
+ r = self._bad_request('Unexpected HTTP request')
341
366
  elif method == 'OPTIONS':
342
367
  r = self._ok()
343
368
  else:
engineio/async_socket.py CHANGED
@@ -56,8 +56,8 @@ class AsyncSocket(base_socket.BaseSocket):
56
56
  """Make sure the client is still sending pings."""
57
57
  if self.closed:
58
58
  raise exceptions.SocketIsClosedError()
59
- if self.last_ping and \
60
- time.time() - self.last_ping > self.server.ping_timeout:
59
+ last_ping = self.last_ping
60
+ if last_ping and time.time() - last_ping > self.server.ping_timeout:
61
61
  self.server.logger.info('%s: Client is gone, closing socket',
62
62
  self.sid)
63
63
  # Passing abort=False here will cause close() to write a
engineio/base_client.py CHANGED
@@ -55,8 +55,14 @@ class BaseClient:
55
55
  self.upgrades = None
56
56
  self.ping_interval = None
57
57
  self.ping_timeout = None
58
- self.http = http_session
59
- self.external_http = http_session is not None
58
+ self.http = None
59
+ self.http_factory = None
60
+ if http_session is not None:
61
+ if callable(http_session):
62
+ self.http_factory = http_session
63
+ else:
64
+ self.http = http_session
65
+ self.external_http = self.http is not None
60
66
  self.handle_sigint = handle_sigint
61
67
  self.ws = None
62
68
  self.read_loop_task = None
engineio/client.py CHANGED
@@ -183,6 +183,8 @@ class Client(base_client.BaseClient):
183
183
  self.queue.task_done()
184
184
  except self.queue_empty:
185
185
  break
186
+ if not self.external_http: # pragma: no cover
187
+ self.http = None
186
188
 
187
189
  def _connect_polling(self, url, headers, engineio_path):
188
190
  """Establish a long-polling connection to the Engine.IO server."""
@@ -274,6 +276,8 @@ class Client(base_client.BaseClient):
274
276
  # so that they are preserved when connecting to the WebSocket route
275
277
  cookies = None
276
278
  extra_options = {}
279
+ if self.http is None and self.http_factory:
280
+ self.http = self.http_factory()
277
281
  if self.http:
278
282
  # cookies
279
283
  ck = SimpleCookie()
@@ -458,7 +462,10 @@ class Client(base_client.BaseClient):
458
462
  self, method, url, headers=None, body=None,
459
463
  timeout=None): # pragma: no cover
460
464
  if self.http is None:
461
- self.http = requests.Session()
465
+ if self.http_factory:
466
+ self.http = self.http_factory()
467
+ else:
468
+ self.http = requests.Session()
462
469
  if not self.ssl_verify:
463
470
  self.http.verify = False
464
471
  try:
engineio/server.py CHANGED
@@ -276,7 +276,19 @@ class Server(base_server.BaseServer):
276
276
  self._log_error_once(f'{e} {sid}', 'bad-sid')
277
277
  r = self._bad_request(f'{e} {sid}')
278
278
  else:
279
- if self.transport(sid) != transport and \
279
+ if not socket.connected:
280
+ # cannot accept requests before connecting
281
+ self._log_error_once(
282
+ f'Socket for session {sid} is not connected',
283
+ 'not-connected')
284
+ r = self._bad_request('Not connected')
285
+ elif socket.upgraded:
286
+ # cannot accept HTTP requests once upgraded
287
+ self._log_error_once(
288
+ f'Unexpected HTTP request for session {sid}',
289
+ 'unexpected-http')
290
+ r = self._bad_request('Unexpected HTTP request')
291
+ elif transport != 'polling' and \
280
292
  transport != upgrade_header:
281
293
  self._log_error_once(
282
294
  f'Invalid transport for session {sid}',
@@ -304,18 +316,31 @@ class Server(base_server.BaseServer):
304
316
  r = self._bad_request(f'Invalid session {sid}')
305
317
  else:
306
318
  socket = self._get_socket(sid)
307
- try:
308
- socket.handle_post_request(environ)
309
- r = self._ok(jsonp_index=jsonp_index)
310
- except exceptions.EngineIOError:
311
- if sid in self.sockets: # pragma: no cover
312
- self.disconnect(sid)
313
- r = self._bad_request()
314
- except: # pragma: no cover
315
- # for any other unexpected errors, we log the error
316
- # and keep going
317
- self.logger.exception('post request handler error')
318
- r = self._ok(jsonp_index=jsonp_index)
319
+ if not socket.connected:
320
+ # cannot accept requests before connecting
321
+ self._log_error_once(
322
+ f'Socket for session {sid} is not connected',
323
+ 'not-connected')
324
+ r = self._bad_request('Not connected')
325
+ elif not socket.upgraded:
326
+ try:
327
+ socket.handle_post_request(environ)
328
+ r = self._ok(jsonp_index=jsonp_index)
329
+ except exceptions.EngineIOError:
330
+ if sid in self.sockets: # pragma: no cover
331
+ self.disconnect(sid)
332
+ r = self._bad_request()
333
+ except: # pragma: no cover
334
+ # for any other unexpected errors, we log the error
335
+ # and keep going
336
+ self.logger.exception('post request handler error')
337
+ r = self._ok(jsonp_index=jsonp_index)
338
+ else:
339
+ # cannot accept HTTP requests once upgraded
340
+ self._log_error_once(
341
+ f'Unexpected HTTP request for session {sid}',
342
+ 'unexpected-http')
343
+ r = self._bad_request('Unexpected HTTP request')
319
344
  elif method == 'OPTIONS':
320
345
  r = self._ok()
321
346
  else:
engineio/socket.py CHANGED
@@ -57,8 +57,8 @@ class Socket(base_socket.BaseSocket):
57
57
  """Make sure the client is still responding to pings."""
58
58
  if self.closed:
59
59
  raise exceptions.SocketIsClosedError()
60
- if self.last_ping and \
61
- time.time() - self.last_ping > self.server.ping_timeout:
60
+ last_ping = self.last_ping
61
+ if last_ping and time.time() - last_ping > self.server.ping_timeout:
62
62
  self.server.logger.info('%s: Client is gone, closing socket',
63
63
  self.sid)
64
64
  # Passing abort=False here will cause close() to write a
engineio/static_files.py CHANGED
@@ -35,6 +35,8 @@ def get_static_file(path, static_files):
35
35
  elif path + '/' in static_files:
36
36
  f = static_files[path + '/']
37
37
  break
38
+ if '../' in extra_path:
39
+ return None
38
40
  if f:
39
41
  if isinstance(f, str):
40
42
  f = {'filename': f}
@@ -1,14 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-engineio
3
- Version: 4.14.0
3
+ Version: 4.15.1
4
4
  Summary: Engine.IO server and client for Python
5
5
  Author-email: Miguel Grinberg <miguel.grinberg@gmail.com>
6
- License: MIT
7
- Project-URL: homepage, https://code.miguelgrinberg.com/miguelgrinberg/python-engineio
8
- Project-URL: documentation, https://python-engineio.readthedocs.io/
9
- Project-URL: repository, https://code.miguelgrinberg.com/miguelgrinberg/python-engineio
10
- Project-URL: issues, https://github.com/miguelgrinberg/python-engineio/issues
11
- Project-URL: changelog, https://code.miguelgrinberg.com/miguelgrinberg/python-engineio/src/branch/main/CHANGES.md
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://code.miguelgrinberg.com/miguelgrinberg/python-engineio
8
+ Project-URL: Documentation, https://python-engineio.readthedocs.io/
9
+ Project-URL: Source Code, https://code.miguelgrinberg.com/miguelgrinberg/python-engineio
10
+ Project-URL: Issue Tracker, https://code.miguelgrinberg.com/miguelgrinberg/python-engineio/issues
11
+ Project-URL: Changelog, https://code.miguelgrinberg.com/miguelgrinberg/python-engineio/src/branch/main/CHANGES.md
12
+ Project-URL: Funding, https://code.miguelgrinberg.com/miguelgrinberg/python-engineio#sponsor-this-project
12
13
  Classifier: Environment :: Web Environment
13
14
  Classifier: Intended Audience :: Developers
14
15
  Classifier: Programming Language :: Python :: 3
@@ -1,19 +1,19 @@
1
1
  engineio/__init__.py,sha256=0R2PY1EXu3sicP7mkA0_QxEVGRlFlgvsxfhByqREE1A,481
2
- engineio/async_client.py,sha256=MuqDjXx7W-Fe8dr29kncI-2BMO0XzvqZHdZ2-kmJThQ,30539
3
- engineio/async_server.py,sha256=7oQClUwwSiPlFFUSEBeE6VuOYnbK2z8FCmRqeWoiiVE,27558
4
- engineio/async_socket.py,sha256=2agIDyicauuHuDHf_2WtUWreq1BP5iu5FQu9tSHWdtY,10827
5
- engineio/base_client.py,sha256=oOdq-zR7kg8QpvAGti0zBIiFBQGyEELwVMZNtcoJ2ig,5827
2
+ engineio/async_client.py,sha256=QIeN6WREOpPOXGk_c4z0HFuUZ-krcb0VNRJdYn3TptE,30996
3
+ engineio/async_server.py,sha256=j9nYtucVXquHvodl0GC_mws6E606JFuImEvtV7TbhEU,29008
4
+ engineio/async_socket.py,sha256=qZYv0BagtaxQvrKK3fwrI4cgf3ShtIRLKdjwxw43WdQ,10834
5
+ engineio/base_client.py,sha256=75L-ydpGSedVLph46aLiwpf8DNPhdgmbkXxH-nSso4E,6033
6
6
  engineio/base_server.py,sha256=tTCqc65Vzf-0Be1uunt1FuGxPOvcpOUCxnT5V2mZCWo,14763
7
7
  engineio/base_socket.py,sha256=PWiJC1msNo-0ctlP3JAwWsngKvnYM-ZjS6B6zzfu-eM,420
8
- engineio/client.py,sha256=STXw-UI3CD9VizbT6A3bbyL2_a1mpRm8TiU6fxJJg7Q,29255
8
+ engineio/client.py,sha256=_pboeKZil8q8kWvQcxYe6Jdu_5IfT5iNpjIDLtbXWUs,29539
9
9
  engineio/exceptions.py,sha256=FyuMb5qhX9CUYP3fEoe1m-faU96ApdQTSbblaaoo8LA,292
10
10
  engineio/json.py,sha256=SG5FTojqd1ix6u0dKXJsZVqqdYioZLO4S2GPL7BKl3U,405
11
11
  engineio/middleware.py,sha256=5NKBXz-ftuFErUB_V9IDvRHaSOsjhtW-NnuJtquB1nc,3750
12
12
  engineio/packet.py,sha256=YO3gmeKUoKyIsUq2e1z7Zifr5PGeS3gnaCeqR7wj5hQ,3198
13
13
  engineio/payload.py,sha256=GIWu0Vnay4WNZlDxHqVgP34tKTBXX58OArJ-mO5zD3E,1539
14
- engineio/server.py,sha256=P6Pa53MRJVoXL_n5tEONuIQoBtOvsdFR5GylKgu5oUE,23088
15
- engineio/socket.py,sha256=WUwGT9MByp04KjHiEnDaESosNsxYxp6AG1tB3pei9eQ,10454
16
- engineio/static_files.py,sha256=pwez9LQFaSQXMbtI0vLyD6UDiokQ4rNfmRYgVLKOthc,2064
14
+ engineio/server.py,sha256=hl7UrTFp6gJT-SCtvJMh9CdUSHr3RqNk5-Hav5sIDH8,24534
15
+ engineio/socket.py,sha256=1xCvZpaoqnud2HNJEs5FXOjOlycjNG5RtSgnHEv8yoE,10461
16
+ engineio/static_files.py,sha256=5h_SMrTbBITg9mYPswe2voA2u3tj9aXz_PuS4OLALj8,2112
17
17
  engineio/async_drivers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  engineio/async_drivers/_websocket_wsgi.py,sha256=8kutiYG0syg3rFeqzMU3Pm-QQwaUx0F9EUUaOfKwPAU,1026
19
19
  engineio/async_drivers/aiohttp.py,sha256=SOU9KOoru_OzxLioSKCYNIZQZLoyf-oxw6-bXc6-_L8,3697
@@ -24,8 +24,8 @@ engineio/async_drivers/gevent_uwsgi.py,sha256=m6ay5dov9FDQl0fbeiKeE-Orh5LiF6zLlY
24
24
  engineio/async_drivers/sanic.py,sha256=GYX8YWR1GbRm-GkMTAQkfkWbY12MOT1IV2DzH0Xx8Ns,4495
25
25
  engineio/async_drivers/threading.py,sha256=ywmG59d4H6OHZjKarBN97-9BHEsRxFEz9YN-E9QAu_I,463
26
26
  engineio/async_drivers/tornado.py,sha256=v9uuGk8_HS6DjhoEKXfjHpki1FnydN4wi7eyBMsUTJA,5908
27
- python_engineio-4.14.0.dist-info/licenses/LICENSE,sha256=yel9Pbwfu82094CLKCzWRtuIev9PUxP-a76NTDFAWpw,1082
28
- python_engineio-4.14.0.dist-info/METADATA,sha256=QZLd2QwRscNvl5JYnURoE2Zu0RhcE5dd_tt4plhmZfA,2496
29
- python_engineio-4.14.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
30
- python_engineio-4.14.0.dist-info/top_level.txt,sha256=u8PmNisCZLwRYcWrNLe9wutQ2tt4zNi8IH362c-HWuA,9
31
- python_engineio-4.14.0.dist-info/RECORD,,
27
+ python_engineio-4.15.1.dist-info/licenses/LICENSE,sha256=yel9Pbwfu82094CLKCzWRtuIev9PUxP-a76NTDFAWpw,1082
28
+ python_engineio-4.15.1.dist-info/METADATA,sha256=OUrDPraYcxJjKEZ4L87sn22DnY2pqcSPHximPyUyQvo,2634
29
+ python_engineio-4.15.1.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
30
+ python_engineio-4.15.1.dist-info/top_level.txt,sha256=u8PmNisCZLwRYcWrNLe9wutQ2tt4zNi8IH362c-HWuA,9
31
+ python_engineio-4.15.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (84.0.0)
2
+ Generator: setuptools (84.2.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5