Bypass Starlette Jinja2Templates - use Jinja2 directly with HTMLResponse

This commit is contained in:
Z User 2026-03-24 06:05:33 +00:00
parent d3c0dfbf5b
commit a2febd7dd9

View File

@ -9,7 +9,7 @@ from pathlib import Path
from typing import Optional, List
from fastapi import APIRouter, Request, Response, Cookie, Form, UploadFile, File, HTTPException
from fastapi.responses import HTMLResponse, JSONResponse, StreamingResponse
from fastapi.templating import Jinja2Templates
from jinja2 import Environment, FileSystemLoader
from pydantic import BaseModel
from loguru import logger
@ -20,15 +20,18 @@ from core.orchestrator import Orchestrator
router = APIRouter()
# Templates - use string path for better compatibility
# Disable cache to avoid hashing issues with Pydantic objects
from jinja2 import Environment, FileSystemLoader
template_env = Environment(
loader=FileSystemLoader(str(Path(__file__).parent / "templates")),
# Templates - use Jinja2 directly without Starlette wrapper
TEMPLATES_DIR = Path(__file__).parent / "templates"
jinja_env = Environment(
loader=FileSystemLoader(str(TEMPLATES_DIR)),
autoescape=True,
cache_size=0, # Disable cache
)
templates = Jinja2Templates(env=template_env)
def render_template(name: str, context: dict) -> str:
"""Render a template with the given context."""
template = jinja_env.get_template(name)
return template.render(**context)
def get_template_settings():
@ -90,28 +93,30 @@ async def landing_page(request: Request):
headers={"Location": "/chat"}
)
return templates.TemplateResponse(
"landing.html",
{"request": request, "settings": get_template_settings()}
)
html = render_template("landing.html", {
"settings": get_template_settings()
})
return HTMLResponse(content=html)
@router.get("/login", response_class=HTMLResponse)
async def login_page(request: Request, error: Optional[str] = None):
"""Login page."""
return templates.TemplateResponse(
"login.html",
{"request": request, "settings": get_template_settings(), "error": error}
)
html = render_template("login.html", {
"settings": get_template_settings(),
"error": error
})
return HTMLResponse(content=html)
@router.get("/signup", response_class=HTMLResponse)
async def signup_page(request: Request, error: Optional[str] = None):
"""Signup page."""
return templates.TemplateResponse(
"signup.html",
{"request": request, "settings": get_template_settings(), "error": error}
)
html = render_template("signup.html", {
"settings": get_template_settings(),
"error": error
})
return HTMLResponse(content=html)
@router.post("/login")
@ -125,11 +130,11 @@ async def login_submit(
user = auth.authenticate(username, password)
if not user:
return templates.TemplateResponse(
"login.html",
{"request": request, "settings": get_template_settings(), "error": "Invalid username or password"},
status_code=401
)
html = render_template("login.html", {
"settings": get_template_settings(),
"error": "Invalid username or password"
})
return HTMLResponse(content=html, status_code=401)
# Create session
token = auth.create_session(user.id)
@ -157,28 +162,28 @@ async def signup_submit(
):
"""Process signup form."""
if password != confirm_password:
return templates.TemplateResponse(
"signup.html",
{"request": request, "settings": get_template_settings(), "error": "Passwords do not match"},
status_code=400
)
html = render_template("signup.html", {
"settings": get_template_settings(),
"error": "Passwords do not match"
})
return HTMLResponse(content=html, status_code=400)
if len(password) < 6:
return templates.TemplateResponse(
"signup.html",
{"request": request, "settings": get_template_settings(), "error": "Password must be at least 6 characters"},
status_code=400
)
html = render_template("signup.html", {
"settings": get_template_settings(),
"error": "Password must be at least 6 characters"
})
return HTMLResponse(content=html, status_code=400)
auth = get_auth_manager()
user = auth.create_user(username, email, password)
if not user:
return templates.TemplateResponse(
"signup.html",
{"request": request, "settings": get_template_settings(), "error": "Username or email already exists"},
status_code=400
)
html = render_template("signup.html", {
"settings": get_template_settings(),
"error": "Username or email already exists"
})
return HTMLResponse(content=html, status_code=400)
# Create session
token = auth.create_session(user.id)
@ -225,15 +230,12 @@ async def chat_page(request: Request, session_token: Optional[str] = Cookie(None
rate_info = auth.check_rate_limit(user.id)
return templates.TemplateResponse(
"chat.html",
{
"request": request,
"settings": get_template_settings(),
"user": user,
"rate_info": rate_info
}
)
html = render_template("chat.html", {
"settings": get_template_settings(),
"user": user,
"rate_info": rate_info
})
return HTMLResponse(content=html)
@router.get("/profile", response_class=HTMLResponse)
@ -254,16 +256,13 @@ async def profile_page(request: Request, session_token: Optional[str] = Cookie(N
documents = auth.get_user_documents(user.id)
rate_info = auth.check_rate_limit(user.id)
return templates.TemplateResponse(
"profile.html",
{
"request": request,
"settings": get_template_settings(),
"user": user,
"documents": documents,
"rate_info": rate_info
}
)
html = render_template("profile.html", {
"settings": get_template_settings(),
"user": user,
"documents": documents,
"rate_info": rate_info
})
return HTMLResponse(content=html)
# ============================================================================