Кажется, у нас возникла "проблема" с Flask (и как таковой Quart), из-за которой мы не можем использовать url_for
маршрутизацию к другим приложениям, даже если мы должны использовать диспетчеризацию приложений. Хотя это можно решить с помощью специального распознавателя URL-адресов, используемого в DispactherMiddleware. Это упомянуто в этой Flask проблеме github Я пытался использовать это, но я думаю, что это нужно изменить, чтобы быть asyn c, но я не знаю как. Все, что я пробую, терпит неудачу
Пока у меня есть этот класс URLForResolver, но он возвращает <coroutine object URLForResolver.__call__ at 0x7fbf7912fac0>
вместо URL
class URLForResolver:
"""
A URL resolver that provides resolution of `url_for` across multiple apps.
"""
def __init__(
self,
apps: List['Quart']) -> None:
self.apps = apps
self.cache = {}
for app in apps:
app.url_build_error_handlers.append(self)
async def __call__(
self,
error,
endpoint: str,
values: Dict) -> None:
if endpoint in self.cache:
print(f'[+] endpoint::: {endpoint} is in cache')
app = self.cache[endpoint]
if app:
async with app.app_context():#, app.test_request_context():
print(f'[+] returning endpoint::: {url_for(endpoint, **values)}')
return url_for(endpoint, **values)
else:
raise error
for app in self.apps:
if app is current_app:
continue
for rule in app.url_map.iter_rules():
print(f'[+] iterating rules::: {rule.endpoint}')
if rule.endpoint == endpoint:
print(f'[+] rule.endpoint == endpoint::: {rule.endpoint} == {endpoint}')
self.cache[endpoint] = app
#return url_for(endpoint, **values)
return self(error, endpoint, values)
self.cache[endpoint] = None
raise error
Я использую класс Resolver следующим образом;
class DispatcherMiddleware:
def __init__(
self,
mounts: Dict[str, ASGIFramework]) -> None:
self.mounts = mounts
self.url_for_resolver = URLForResolver(list(self.mounts.values()))
async def __call__(
self,
scope: dict,
receive: Callable,
send: Callable) -> None:
for path, app in self.mounts.items():
if scope['type'] not in {'http', 'websocket'}:
return await invoke_asgi(app, scope, receive, send)
if scope['path'].startswith(path):
scope['path'] = scope['path'][len(path) :] or '/'
return await invoke_asgi(app, scope, receive, send)
await send({
'type': 'http.response.start',
'status': 404,
'headers': [(b'content-length', b'0')]
})
await send({'type': 'http.response.body'})