asgi/wsgi mounting implemented

This commit is contained in:
Илья Глазунов
2025-12-03 12:10:28 +03:00
parent 831eee5d01
commit 0d0d1aec80
13 changed files with 2528 additions and 7 deletions
+68 -3
View File
@@ -10,7 +10,7 @@ from pathlib import Path
from typing import Optional, Dict, Any
from .config import Config
from .extensions import ExtensionManager
from .extensions import ExtensionManager, ASGIExtension
from .logging_utils import get_logger
from . import __version__
@@ -30,6 +30,11 @@ class PyServeMiddleware:
start_time = time.time()
request = Request(scope, receive)
asgi_handled = await self._try_asgi_mount(scope, receive, send, request, start_time)
if asgi_handled:
return
response = await self.extension_manager.process_request(request)
if response is None:
@@ -39,6 +44,68 @@ class PyServeMiddleware:
response = await self.extension_manager.process_response(request, response)
response.headers["Server"] = f"pyserve/{__version__}"
self._log_access(request, response, start_time)
await response(scope, receive, send)
async def _try_asgi_mount(
self,
scope: Scope,
receive: Receive,
send: Send,
request: Request,
start_time: float
) -> bool:
for extension in self.extension_manager.extensions:
if isinstance(extension, ASGIExtension):
mount = extension.get_asgi_handler(request)
if mount is not None:
modified_scope = dict(scope)
if mount.strip_path:
modified_scope["path"] = mount.get_modified_path(request.url.path)
modified_scope["root_path"] = scope.get("root_path", "") + mount.path
logger.debug(
f"Routing to ASGI mount '{mount.name}': "
f"{request.url.path} -> {modified_scope['path']}"
)
try:
response_started = False
status_code = 0
async def send_wrapper(message: Dict[str, Any]) -> None:
nonlocal response_started, status_code
if message["type"] == "http.response.start":
response_started = True
status_code = message.get("status", 0)
await send(message)
await mount.app(modified_scope, receive, send_wrapper)
process_time = round((time.time() - start_time) * 1000, 2)
self.access_logger.info(
"ASGI request",
client_ip=request.client.host if request.client else "unknown",
method=request.method,
path=str(request.url.path),
mount=mount.name,
status_code=status_code,
process_time_ms=process_time,
user_agent=request.headers.get("user-agent", "")
)
return True
except Exception as e:
logger.error(f"Error in ASGI mount '{mount.name}': {e}")
error_response = PlainTextResponse(
"500 Internal Server Error",
status_code=500
)
await error_response(scope, receive, send)
return True
return False
def _log_access(self, request: Request, response: Response, start_time: float) -> None:
client_ip = request.client.host if request.client else "unknown"
method = request.method
path = str(request.url.path)
@@ -58,8 +125,6 @@ class PyServeMiddleware:
user_agent=request.headers.get("user-agent", "")
)
await response(scope, receive, send)
class PyServeServer:
def __init__(self, config: Config):