reflex 0.6.8a1__py3-none-any.whl → 0.6.8a2__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.
Potentially problematic release.
This version of reflex might be problematic. Click here for more details.
- reflex/app.py +0 -6
- reflex/config.py +0 -5
- reflex/event.py +7 -2
- reflex/testing.py +5 -16
- reflex/utils/console.py +1 -6
- reflex/vars/base.py +1 -1
- {reflex-0.6.8a1.dist-info → reflex-0.6.8a2.dist-info}/METADATA +1 -3
- {reflex-0.6.8a1.dist-info → reflex-0.6.8a2.dist-info}/RECORD +11 -12
- reflex/proxy.py +0 -119
- {reflex-0.6.8a1.dist-info → reflex-0.6.8a2.dist-info}/LICENSE +0 -0
- {reflex-0.6.8a1.dist-info → reflex-0.6.8a2.dist-info}/WHEEL +0 -0
- {reflex-0.6.8a1.dist-info → reflex-0.6.8a2.dist-info}/entry_points.txt +0 -0
reflex/app.py
CHANGED
|
@@ -331,12 +331,6 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
331
331
|
|
|
332
332
|
self.register_lifespan_task(windows_hot_reload_lifespan_hack)
|
|
333
333
|
|
|
334
|
-
# Enable proxying to frontend server.
|
|
335
|
-
if not environment.REFLEX_BACKEND_ONLY.get():
|
|
336
|
-
from reflex.proxy import proxy_middleware
|
|
337
|
-
|
|
338
|
-
self.register_lifespan_task(proxy_middleware)
|
|
339
|
-
|
|
340
334
|
def _enable_state(self) -> None:
|
|
341
335
|
"""Enable state for the app."""
|
|
342
336
|
if not self.state:
|
reflex/config.py
CHANGED
|
@@ -26,7 +26,6 @@ from typing import (
|
|
|
26
26
|
|
|
27
27
|
from typing_extensions import Annotated, get_type_hints
|
|
28
28
|
|
|
29
|
-
from reflex.utils.console import set_log_level
|
|
30
29
|
from reflex.utils.exceptions import ConfigError, EnvironmentVarValueError
|
|
31
30
|
from reflex.utils.types import GenericType, is_union, value_inside_optional
|
|
32
31
|
|
|
@@ -600,7 +599,6 @@ class Config(Base):
|
|
|
600
599
|
class Config:
|
|
601
600
|
"""Pydantic config for the config."""
|
|
602
601
|
|
|
603
|
-
use_enum_values = False
|
|
604
602
|
validate_assignment = True
|
|
605
603
|
|
|
606
604
|
# The name of the app (should match the name of the app directory).
|
|
@@ -720,9 +718,6 @@ class Config(Base):
|
|
|
720
718
|
self._non_default_attributes.update(kwargs)
|
|
721
719
|
self._replace_defaults(**kwargs)
|
|
722
720
|
|
|
723
|
-
# Set the log level for this process
|
|
724
|
-
set_log_level(self.loglevel)
|
|
725
|
-
|
|
726
721
|
if (
|
|
727
722
|
self.state_manager_mode == constants.StateManagerMode.REDIS
|
|
728
723
|
and not self.redis_url
|
reflex/event.py
CHANGED
|
@@ -437,6 +437,7 @@ class EventChain(EventActionsMixin):
|
|
|
437
437
|
value: EventType,
|
|
438
438
|
args_spec: ArgsSpec | Sequence[ArgsSpec],
|
|
439
439
|
key: Optional[str] = None,
|
|
440
|
+
**event_chain_kwargs,
|
|
440
441
|
) -> Union[EventChain, Var]:
|
|
441
442
|
"""Create an event chain from a variety of input types.
|
|
442
443
|
|
|
@@ -444,6 +445,7 @@ class EventChain(EventActionsMixin):
|
|
|
444
445
|
value: The value to create the event chain from.
|
|
445
446
|
args_spec: The args_spec of the event trigger being bound.
|
|
446
447
|
key: The key of the event trigger being bound.
|
|
448
|
+
**event_chain_kwargs: Additional kwargs to pass to the EventChain constructor.
|
|
447
449
|
|
|
448
450
|
Returns:
|
|
449
451
|
The event chain.
|
|
@@ -462,6 +464,7 @@ class EventChain(EventActionsMixin):
|
|
|
462
464
|
value=value.guess_type(),
|
|
463
465
|
args_spec=args_spec,
|
|
464
466
|
key=key,
|
|
467
|
+
**event_chain_kwargs,
|
|
465
468
|
)
|
|
466
469
|
else:
|
|
467
470
|
raise ValueError(
|
|
@@ -501,7 +504,9 @@ class EventChain(EventActionsMixin):
|
|
|
501
504
|
result = call_event_fn(value, args_spec, key=key)
|
|
502
505
|
if isinstance(result, Var):
|
|
503
506
|
# Recursively call this function if the lambda returned an EventChain Var.
|
|
504
|
-
return cls.create(
|
|
507
|
+
return cls.create(
|
|
508
|
+
value=result, args_spec=args_spec, key=key, **event_chain_kwargs
|
|
509
|
+
)
|
|
505
510
|
events = [*result]
|
|
506
511
|
|
|
507
512
|
# Otherwise, raise an error.
|
|
@@ -518,7 +523,7 @@ class EventChain(EventActionsMixin):
|
|
|
518
523
|
return cls(
|
|
519
524
|
events=events,
|
|
520
525
|
args_spec=args_spec,
|
|
521
|
-
|
|
526
|
+
**event_chain_kwargs,
|
|
522
527
|
)
|
|
523
528
|
|
|
524
529
|
|
reflex/testing.py
CHANGED
|
@@ -44,7 +44,6 @@ import reflex.utils.format
|
|
|
44
44
|
import reflex.utils.prerequisites
|
|
45
45
|
import reflex.utils.processes
|
|
46
46
|
from reflex.config import environment
|
|
47
|
-
from reflex.proxy import proxy_middleware
|
|
48
47
|
from reflex.state import (
|
|
49
48
|
BaseState,
|
|
50
49
|
StateManager,
|
|
@@ -299,9 +298,6 @@ class AppHarness:
|
|
|
299
298
|
self.state_manager = StateManagerRedis.create(self.app_instance.state)
|
|
300
299
|
else:
|
|
301
300
|
self.state_manager = self.app_instance._state_manager
|
|
302
|
-
# Disable proxy for app harness tests.
|
|
303
|
-
if proxy_middleware in self.app_instance.lifespan_tasks:
|
|
304
|
-
self.app_instance.lifespan_tasks.remove(proxy_middleware)
|
|
305
301
|
|
|
306
302
|
def _reload_state_module(self):
|
|
307
303
|
"""Reload the rx.State module to avoid conflict when reloading."""
|
|
@@ -369,12 +365,9 @@ class AppHarness:
|
|
|
369
365
|
def _start_frontend(self):
|
|
370
366
|
# Set up the frontend.
|
|
371
367
|
with chdir(self.app_path):
|
|
372
|
-
backend_host, backend_port = self._poll_for_servers().getsockname()
|
|
373
368
|
config = reflex.config.get_config()
|
|
374
|
-
config.backend_port = backend_port
|
|
375
369
|
config.api_url = "http://{0}:{1}".format(
|
|
376
|
-
|
|
377
|
-
backend_port,
|
|
370
|
+
*self._poll_for_servers().getsockname(),
|
|
378
371
|
)
|
|
379
372
|
reflex.utils.build.setup_frontend(self.app_path)
|
|
380
373
|
|
|
@@ -399,7 +392,6 @@ class AppHarness:
|
|
|
399
392
|
self.frontend_url = m.group(1)
|
|
400
393
|
config = reflex.config.get_config()
|
|
401
394
|
config.deploy_url = self.frontend_url
|
|
402
|
-
config.frontend_port = int(self.frontend_url.rpartition(":")[2])
|
|
403
395
|
break
|
|
404
396
|
if self.frontend_url is None:
|
|
405
397
|
raise RuntimeError("Frontend did not start")
|
|
@@ -923,20 +915,17 @@ class AppHarnessProd(AppHarness):
|
|
|
923
915
|
root=web_root,
|
|
924
916
|
error_page_map=error_page_map,
|
|
925
917
|
) as self.frontend_server:
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
918
|
+
self.frontend_url = "http://localhost:{1}".format(
|
|
919
|
+
*self.frontend_server.socket.getsockname()
|
|
920
|
+
)
|
|
929
921
|
self.frontend_server.serve_forever()
|
|
930
922
|
|
|
931
923
|
def _start_frontend(self):
|
|
932
924
|
# Set up the frontend.
|
|
933
925
|
with chdir(self.app_path):
|
|
934
|
-
backend_host, backend_port = self._poll_for_servers().getsockname()
|
|
935
926
|
config = reflex.config.get_config()
|
|
936
|
-
config.backend_port = backend_port
|
|
937
927
|
config.api_url = "http://{0}:{1}".format(
|
|
938
|
-
|
|
939
|
-
backend_port,
|
|
928
|
+
*self._poll_for_servers().getsockname(),
|
|
940
929
|
)
|
|
941
930
|
reflex.reflex.export(
|
|
942
931
|
zipping=False,
|
reflex/utils/console.py
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import os
|
|
6
|
-
|
|
7
5
|
from rich.console import Console
|
|
8
6
|
from rich.progress import MofNCompleteColumn, Progress, TimeElapsedColumn
|
|
9
7
|
from rich.prompt import Prompt
|
|
@@ -14,7 +12,7 @@ from reflex.constants import LogLevel
|
|
|
14
12
|
_console = Console()
|
|
15
13
|
|
|
16
14
|
# The current log level.
|
|
17
|
-
_LOG_LEVEL = LogLevel.
|
|
15
|
+
_LOG_LEVEL = LogLevel.INFO
|
|
18
16
|
|
|
19
17
|
# Deprecated features who's warning has been printed.
|
|
20
18
|
_EMITTED_DEPRECATION_WARNINGS = set()
|
|
@@ -63,9 +61,6 @@ def set_log_level(log_level: LogLevel):
|
|
|
63
61
|
raise ValueError(f"Invalid log level: {log_level}") from ae
|
|
64
62
|
|
|
65
63
|
global _LOG_LEVEL
|
|
66
|
-
if log_level != _LOG_LEVEL:
|
|
67
|
-
# Set the loglevel persistently for subprocesses
|
|
68
|
-
os.environ["LOGLEVEL"] = log_level.value
|
|
69
64
|
_LOG_LEVEL = log_level
|
|
70
65
|
|
|
71
66
|
|
reflex/vars/base.py
CHANGED
|
@@ -581,7 +581,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
581
581
|
|
|
582
582
|
# Try to pull the imports and hooks from contained values.
|
|
583
583
|
if not isinstance(value, str):
|
|
584
|
-
return LiteralVar.create(value)
|
|
584
|
+
return LiteralVar.create(value, _var_data=_var_data)
|
|
585
585
|
|
|
586
586
|
if _var_is_string is False or _var_is_local is True:
|
|
587
587
|
return cls(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: reflex
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.8a2
|
|
4
4
|
Summary: Web apps in pure Python.
|
|
5
5
|
Home-page: https://reflex.dev
|
|
6
6
|
License: Apache-2.0
|
|
@@ -15,9 +15,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
-
Provides-Extra: proxy
|
|
19
18
|
Requires-Dist: alembic (>=1.11.1,<2.0)
|
|
20
|
-
Requires-Dist: asgiproxy (==0.1.1) ; extra == "proxy"
|
|
21
19
|
Requires-Dist: build (>=1.0.3,<2.0)
|
|
22
20
|
Requires-Dist: charset-normalizer (>=3.3.2,<4.0)
|
|
23
21
|
Requires-Dist: distro (>=1.8.0,<2.0) ; sys_platform == "linux"
|
|
@@ -40,7 +40,7 @@ reflex/__init__.py,sha256=c00VJtWXWwKr8YjDAJXT0_57PTbBZDZ9z5Djmzorxn0,10720
|
|
|
40
40
|
reflex/__init__.pyi,sha256=5V_z_NFVSF048DFv1aAfLYMi07fUB-j_L8gQc5SxU8k,11273
|
|
41
41
|
reflex/__main__.py,sha256=6cVrGEyT3j3tEvlEVUatpaYfbB5EF3UVY-6vc_Z7-hw,108
|
|
42
42
|
reflex/admin.py,sha256=_3pkkauMiTGJJ0kwAEBnsUWAgZZ_1WNnCaaObbhpmUI,374
|
|
43
|
-
reflex/app.py,sha256=
|
|
43
|
+
reflex/app.py,sha256=6CSeEcc_h4aEYmVBzssbgZbTt1Xm9Bm3J0-koTGDZuk,56487
|
|
44
44
|
reflex/app_mixins/__init__.py,sha256=Oegz3-gZLP9p2OAN5ALNbsgxuNQfS6lGZgQA8cc-9mQ,137
|
|
45
45
|
reflex/app_mixins/lifespan.py,sha256=IG72wp1Kas2polEP6Y1nB0wFPN3J4Kh0JAHvbQ-7wZ8,3185
|
|
46
46
|
reflex/app_mixins/middleware.py,sha256=V5J06Ux9qZIHFX0pnz8qd3EuHHI8KIvtEKpfave_kjI,3209
|
|
@@ -323,7 +323,7 @@ reflex/components/tags/iter_tag.py,sha256=kdJeQbCJ02Cn5VPDRERywu8bJNrTgreIi3ZyOA
|
|
|
323
323
|
reflex/components/tags/match_tag.py,sha256=mqQF6fHhOSGSMdiaJ7YlwXSMhRtDmmIBu1Gw-VQQ324,586
|
|
324
324
|
reflex/components/tags/tag.py,sha256=5nlh1SU6Mwod8vyGCsV-iixd4xa_4cqU2vsBxHEA5ak,3084
|
|
325
325
|
reflex/components/tags/tagless.py,sha256=qO7Gm4V0ITDyymHkyltfz53155ZBt-W_WIPDYy93ca0,587
|
|
326
|
-
reflex/config.py,sha256=
|
|
326
|
+
reflex/config.py,sha256=WZb8CTKqoMjcTAAeRK-5LvMAWE5TLibUgWt6S01xWOU,27272
|
|
327
327
|
reflex/constants/__init__.py,sha256=VIF5rXe4-R_gdPX-G2dM8tw9X206GhjXAhWdOPtxctM,1974
|
|
328
328
|
reflex/constants/base.py,sha256=9PxiZPfU6xktVZuJYVOB3mYF7_oMsiKE7Bq0E5hU2ug,7444
|
|
329
329
|
reflex/constants/colors.py,sha256=cgLn8iEWtlpjQgbhhlCOGjbhfOULKnzqqzPph63SJoI,1613
|
|
@@ -338,7 +338,7 @@ reflex/constants/style.py,sha256=-LTofj8rBEAYEx8_Zj4Tda_EEPvgp2BjpLinarNOu2o,475
|
|
|
338
338
|
reflex/constants/utils.py,sha256=HGOSq9c-xGbCb1xoLAGLBdc-FOE8iuBzvuU24zSfsV0,789
|
|
339
339
|
reflex/custom_components/__init__.py,sha256=R4zsvOi4dfPmHc18KEphohXnQFBPnUCb50cMR5hSLDE,36
|
|
340
340
|
reflex/custom_components/custom_components.py,sha256=6OJMZ8AVk_DE-3UV0m9yjD_fLjyDZMasNtjrDGRy94o,33053
|
|
341
|
-
reflex/event.py,sha256=
|
|
341
|
+
reflex/event.py,sha256=mFoJ9LEZrOqZ8vo13KZadKNZu8bvZmHSkUDaOZf-Wtc,60625
|
|
342
342
|
reflex/experimental/__init__.py,sha256=Tzh48jIncw2YzRFHh2SXWZ599TsHeY6_RrrWdK6gE2A,2085
|
|
343
343
|
reflex/experimental/assets.py,sha256=9qkhgcNo-xfpjHVZ1-lN79tB5qbWw_2nYaVliaV4Z4A,1098
|
|
344
344
|
reflex/experimental/client_state.py,sha256=-dCjtd_wINu_OFcH9i3NfagoiDwu_OMm-VQLGO20Kps,9107
|
|
@@ -357,17 +357,16 @@ reflex/middleware/hydrate_middleware.py,sha256=KvFppl4ca75bsjos5boy8EGwsRBZ9jI6Z
|
|
|
357
357
|
reflex/middleware/middleware.py,sha256=9eASK3MrbK1AvT2Sx5GFxXNwSuNW8_LTRGvPY1JccU4,1171
|
|
358
358
|
reflex/model.py,sha256=u19v2w-1MAeru46Hht8UscisIq5Y5EMuNo9xVbXIXEg,17352
|
|
359
359
|
reflex/page.py,sha256=2vnjP1SPRZY_l_E3uog0al3s2a_evzjCYUB4UTK8FNE,2388
|
|
360
|
-
reflex/proxy.py,sha256=VJg8pV6DKpY3Zuw4bY0wvAjYOK-21OpINMtjL7XBLDo,3730
|
|
361
360
|
reflex/reflex.py,sha256=v2rdQHfKGQ9_klXEf96NbAEmeMV3SQaORl9v0RYGxWg,17000
|
|
362
361
|
reflex/route.py,sha256=WZS7stKgO94nekFFYHaOqNgN3zZGpJb3YpGF4ViTHmw,4198
|
|
363
362
|
reflex/state.py,sha256=s0f1fkBGVawbxXLdohNH-cu_YxN_7ZWYBKObhyZgseM,141647
|
|
364
363
|
reflex/style.py,sha256=Djj6TUbDORun3nSwny6IQL8vYdlCON_b8qITkbSZ5Oc,12571
|
|
365
|
-
reflex/testing.py,sha256=
|
|
364
|
+
reflex/testing.py,sha256=90KTRRI5dzww_wwMQshm-TisbnQjPfkMNGYkvqeaRS8,34795
|
|
366
365
|
reflex/utils/__init__.py,sha256=y-AHKiRQAhk2oAkvn7W8cRVTZVK625ff8tTwvZtO7S4,24
|
|
367
366
|
reflex/utils/build.py,sha256=gbviqfS7x8yoIA5GZyzupR30GmlxP2WF4kzMRbTVs80,8393
|
|
368
367
|
reflex/utils/codespaces.py,sha256=tKmju4aGzDMPy76_eQSzJd3RYmVmiiNZy3Yc0e3zG_w,2856
|
|
369
368
|
reflex/utils/compat.py,sha256=nYlAZqrO1Co7WJefmlIeQMzQc-KCfc9eqRX1zkpD3Ok,2527
|
|
370
|
-
reflex/utils/console.py,sha256=
|
|
369
|
+
reflex/utils/console.py,sha256=NvFK1G_X8oSdA-85bi2tvc5MVwSUHeIukjDkVIXF67o,7776
|
|
371
370
|
reflex/utils/exceptions.py,sha256=j1vlgdFhGx7L2uM4VNmhsj0kW1YYuIlVE0Uq6-mNWeo,5781
|
|
372
371
|
reflex/utils/exec.py,sha256=yrehsUXjNisQqyZr53Op2c7uwLdcFRo5iFgP-t5JB_w,16313
|
|
373
372
|
reflex/utils/export.py,sha256=7zBwzRznOlzybzSNzYZWON3YluFh-bYW79i4ZCHVbtY,2360
|
|
@@ -385,14 +384,14 @@ reflex/utils/serializers.py,sha256=j-Hvo-sCEEVBEuFxlDHpZLpJDeHlby9qNzhJD8DOnM4,1
|
|
|
385
384
|
reflex/utils/telemetry.py,sha256=kOxP6P9Ms717QINw453avxSbMrg4iewRK3UpcNlSQ3Q,5764
|
|
386
385
|
reflex/utils/types.py,sha256=J9wFZfjZ4uL5pbA28_Dst0m-so3T4kfBFdQ9ElQHcFI,26258
|
|
387
386
|
reflex/vars/__init__.py,sha256=2Kv6Oh9g3ISZFESjL1al8KiO7QBZUXmLKGMCBsP-DoY,1243
|
|
388
|
-
reflex/vars/base.py,sha256=
|
|
387
|
+
reflex/vars/base.py,sha256=3Sz8zSoUA46dOrbB1Uo6ymr-q1MjDw2dp6DXIjnxjw4,89533
|
|
389
388
|
reflex/vars/datetime.py,sha256=BnEZmxCpOjtvlPw6sfdjCoRJgefFlRFC4y-lqxC5MeA,5673
|
|
390
389
|
reflex/vars/function.py,sha256=ZxeznTQqprp4ernr8ADk5B4ztbuwqTMGnHo9zVCHDpw,14583
|
|
391
390
|
reflex/vars/number.py,sha256=3dsxSqZOxEc47Fx19YlQaD0jlqHEouxjI0z5Zx_y_7U,27484
|
|
392
391
|
reflex/vars/object.py,sha256=_wQMRaJV9IqanKLNwOLw-OX0A0fju40w74QjEdpVnoY,14310
|
|
393
392
|
reflex/vars/sequence.py,sha256=i3wMyAxe63fxkvIK9MSLHc772ACHJUpbWp9qRY-VBok,50829
|
|
394
|
-
reflex-0.6.
|
|
395
|
-
reflex-0.6.
|
|
396
|
-
reflex-0.6.
|
|
397
|
-
reflex-0.6.
|
|
398
|
-
reflex-0.6.
|
|
393
|
+
reflex-0.6.8a2.dist-info/LICENSE,sha256=dw3zLrp9f5ObD7kqS32vWfhcImfO52PMmRqvtxq_YEE,11358
|
|
394
|
+
reflex-0.6.8a2.dist-info/METADATA,sha256=PQrESKn56QZHwWOcPwtdjS70E6gPz3FVVf6noYbwjAQ,12102
|
|
395
|
+
reflex-0.6.8a2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
396
|
+
reflex-0.6.8a2.dist-info/entry_points.txt,sha256=H1Z5Yat_xJfy0dRT1Frk2PkO_p41Xy7fCKlj4FcdL9o,44
|
|
397
|
+
reflex-0.6.8a2.dist-info/RECORD,,
|
reflex/proxy.py
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
"""Handle proxying frontend requests from the backend server."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import asyncio
|
|
6
|
-
from contextlib import asynccontextmanager
|
|
7
|
-
from typing import Any, AsyncGenerator
|
|
8
|
-
from urllib.parse import urlparse
|
|
9
|
-
|
|
10
|
-
from fastapi import FastAPI
|
|
11
|
-
from starlette.types import ASGIApp, Receive, Scope, Send
|
|
12
|
-
|
|
13
|
-
from .config import get_config
|
|
14
|
-
from .utils import console
|
|
15
|
-
|
|
16
|
-
try:
|
|
17
|
-
import aiohttp
|
|
18
|
-
from asgiproxy.config import BaseURLProxyConfigMixin, ProxyConfig
|
|
19
|
-
from asgiproxy.context import ProxyContext
|
|
20
|
-
from asgiproxy.proxies.http import proxy_http
|
|
21
|
-
from asgiproxy.simple_proxy import make_simple_proxy_app
|
|
22
|
-
except ImportError:
|
|
23
|
-
|
|
24
|
-
@asynccontextmanager
|
|
25
|
-
async def proxy_middleware(*args, **kwargs) -> AsyncGenerator[None, None]:
|
|
26
|
-
"""A no-op proxy middleware for when asgiproxy is not installed.
|
|
27
|
-
|
|
28
|
-
Args:
|
|
29
|
-
*args: The positional arguments.
|
|
30
|
-
**kwargs: The keyword arguments.
|
|
31
|
-
|
|
32
|
-
Yields:
|
|
33
|
-
None
|
|
34
|
-
"""
|
|
35
|
-
yield
|
|
36
|
-
else:
|
|
37
|
-
MAX_PROXY_RETRY = 25
|
|
38
|
-
|
|
39
|
-
async def proxy_http_with_retry(
|
|
40
|
-
*,
|
|
41
|
-
context: ProxyContext,
|
|
42
|
-
scope: Scope,
|
|
43
|
-
receive: Receive,
|
|
44
|
-
send: Send,
|
|
45
|
-
) -> Any:
|
|
46
|
-
"""Proxy an HTTP request with retries.
|
|
47
|
-
|
|
48
|
-
Args:
|
|
49
|
-
context: The proxy context.
|
|
50
|
-
scope: The request scope.
|
|
51
|
-
receive: The receive channel.
|
|
52
|
-
send: The send channel.
|
|
53
|
-
|
|
54
|
-
Returns:
|
|
55
|
-
The response from `proxy_http`.
|
|
56
|
-
"""
|
|
57
|
-
for _attempt in range(MAX_PROXY_RETRY):
|
|
58
|
-
try:
|
|
59
|
-
return await proxy_http(
|
|
60
|
-
context=context,
|
|
61
|
-
scope=scope,
|
|
62
|
-
receive=receive,
|
|
63
|
-
send=send,
|
|
64
|
-
)
|
|
65
|
-
except aiohttp.ClientError as err: # noqa: PERF203
|
|
66
|
-
console.debug(
|
|
67
|
-
f"Retrying request {scope['path']} due to client error {err!r}."
|
|
68
|
-
)
|
|
69
|
-
await asyncio.sleep(0.3)
|
|
70
|
-
except Exception as ex:
|
|
71
|
-
console.debug(
|
|
72
|
-
f"Retrying request {scope['path']} due to unhandled exception {ex!r}."
|
|
73
|
-
)
|
|
74
|
-
await asyncio.sleep(0.3)
|
|
75
|
-
|
|
76
|
-
def _get_proxy_app_with_context(frontend_host: str) -> tuple[ProxyContext, ASGIApp]:
|
|
77
|
-
"""Get the proxy app with the given frontend host.
|
|
78
|
-
|
|
79
|
-
Args:
|
|
80
|
-
frontend_host: The frontend host to proxy requests to.
|
|
81
|
-
|
|
82
|
-
Returns:
|
|
83
|
-
The proxy context and app.
|
|
84
|
-
"""
|
|
85
|
-
|
|
86
|
-
class LocalProxyConfig(BaseURLProxyConfigMixin, ProxyConfig):
|
|
87
|
-
upstream_base_url = frontend_host
|
|
88
|
-
rewrite_host_header = urlparse(upstream_base_url).netloc
|
|
89
|
-
|
|
90
|
-
proxy_context = ProxyContext(LocalProxyConfig())
|
|
91
|
-
proxy_app = make_simple_proxy_app(
|
|
92
|
-
proxy_context, proxy_http_handler=proxy_http_with_retry
|
|
93
|
-
)
|
|
94
|
-
return proxy_context, proxy_app
|
|
95
|
-
|
|
96
|
-
@asynccontextmanager
|
|
97
|
-
async def proxy_middleware( # pyright: ignore[reportGeneralTypeIssues]
|
|
98
|
-
app: FastAPI,
|
|
99
|
-
) -> AsyncGenerator[None, None]:
|
|
100
|
-
"""A middleware to proxy requests to the separate frontend server.
|
|
101
|
-
|
|
102
|
-
The proxy is installed on the / endpoint of the FastAPI instance.
|
|
103
|
-
|
|
104
|
-
Args:
|
|
105
|
-
app: The FastAPI instance.
|
|
106
|
-
|
|
107
|
-
Yields:
|
|
108
|
-
None
|
|
109
|
-
"""
|
|
110
|
-
config = get_config()
|
|
111
|
-
backend_port = config.backend_port
|
|
112
|
-
frontend_host = f"http://localhost:{config.frontend_port}"
|
|
113
|
-
proxy_context, proxy_app = _get_proxy_app_with_context(frontend_host)
|
|
114
|
-
app.mount("/", proxy_app)
|
|
115
|
-
console.debug(
|
|
116
|
-
f"Proxying '/' requests on port {backend_port} to {frontend_host}"
|
|
117
|
-
)
|
|
118
|
-
async with proxy_context:
|
|
119
|
-
yield
|
|
File without changes
|
|
File without changes
|
|
File without changes
|