middleware fix for path-based vendor url

This commit is contained in:
2025-11-09 18:47:53 +01:00
parent 79dfcab09f
commit adbcee4ce3
13 changed files with 2078 additions and 810 deletions

View File

@@ -1,9 +1,17 @@
# middleware/theme_context.py
"""
Theme Context Middleware
Injects vendor-specific theme into request context
Theme Context Middleware (Class-Based)
Injects vendor-specific theme into request context.
Class-based middleware provides:
- Better state management
- Easier testing
- Standard ASGI pattern
"""
import logging
from starlette.middleware.base import BaseHTTPMiddleware
from fastapi import Request
from sqlalchemy.orm import Session
@@ -31,7 +39,7 @@ class ThemeContextManager:
return theme.to_dict()
# Return default theme
return get_default_theme()
return ThemeContextManager.get_default_theme()
@staticmethod
def get_default_theme() -> dict:
@@ -76,40 +84,68 @@ class ThemeContextManager:
}
async def theme_context_middleware(request: Request, call_next):
class ThemeContextMiddleware(BaseHTTPMiddleware):
"""
Middleware to inject theme context into request state.
This runs AFTER vendor_context_middleware has set request.state.vendor
Class-based middleware provides:
- Better state management
- Easier testing
- Standard ASGI pattern
Runs LAST in middleware chain (after vendor_context_middleware and context_middleware).
Depends on:
request.state.vendor (set by vendor_context_middleware)
Sets:
request.state.theme: Theme dictionary
"""
# Only inject theme for shop pages (not admin or API)
if hasattr(request.state, 'vendor') and request.state.vendor:
vendor = request.state.vendor
# Get database session
db_gen = get_db()
db = next(db_gen)
async def dispatch(self, request: Request, call_next):
"""
Load and inject theme context.
"""
# Only inject theme for shop pages (not admin or API)
if hasattr(request.state, 'vendor') and request.state.vendor:
vendor = request.state.vendor
try:
# Get vendor theme
theme = ThemeContextManager.get_vendor_theme(db, vendor.id)
request.state.theme = theme
# Get database session
db_gen = get_db()
db = next(db_gen)
logger.debug(
f"Theme loaded for vendor {vendor.name}: {theme['theme_name']}"
)
except Exception as e:
logger.error(f"Failed to load theme for vendor {vendor.id}: {e}")
# Fallback to default theme
try:
# Get vendor theme
theme = ThemeContextManager.get_vendor_theme(db, vendor.id)
request.state.theme = theme
logger.debug(
f"[THEME] Theme loaded for vendor",
extra={
"vendor_id": vendor.id,
"vendor_name": vendor.name,
"theme_name": theme.get('theme_name', 'default'),
}
)
except Exception as e:
logger.error(
f"[THEME] Failed to load theme for vendor {vendor.id}: {e}",
exc_info=True
)
# Fallback to default theme
request.state.theme = ThemeContextManager.get_default_theme()
finally:
db.close()
else:
# No vendor context, use default theme
request.state.theme = ThemeContextManager.get_default_theme()
finally:
db.close()
else:
# No vendor context, use default theme
request.state.theme = ThemeContextManager.get_default_theme()
logger.debug(
"[THEME] No vendor context, using default theme",
extra={"has_vendor": False}
)
response = await call_next(request)
return response
# Continue processing
response = await call_next(request)
return response
def get_current_theme(request: Request) -> dict: