File size: 2,070 Bytes
6078ec2
 
dccc925
6078ec2
 
 
 
3739378
70b69aa
dccc925
 
 
 
 
 
 
 
a43aaf6
 
 
70b69aa
3739378
 
70b69aa
 
3739378
 
70b69aa
 
3739378
 
00dd25e
3739378
 
 
 
 
 
 
 
70b69aa
 
 
3739378
70b69aa
9088c1f
dccc925
 
3739378
 
dccc925
 
 
a43aaf6
dccc925
 
9088c1f
dccc925
 
 
 
 
 
 
 
 
 
3739378
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
"""
Main entry point for Rubric AI.

Runs both FastAPI backend and NiceGUI frontend on a single Uvicorn process.
Designed for deployment on Hugging Face Spaces (port 7860).
"""

import re
from starlette.middleware.base import BaseHTTPMiddleware
from backend.app import create_app
from backend.core.config import settings
from frontend.ui import init_frontend
from nicegui import ui

# Create FastAPI application
app = create_app()

# Import API routes (registers @app decorators)
import frontend.api_routes  # noqa: F401


# Middleware to allow iframe embedding on HF Spaces
class AllowIframeMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request, call_next):
        response = await call_next(request)

        # Remove X-Frame-Options to allow HF Spaces iframe embedding
        if "x-frame-options" in response.headers:
            del response.headers["x-frame-options"]

        # Remove or modify Content-Security-Policy frame-ancestors directive
        if "content-security-policy" in response.headers:
            csp = response.headers["content-security-policy"]
            # Remove frame-ancestors directive entirely to allow any iframe embedding
            csp = re.sub(r"frame-ancestors\s+[^;]+;?\s*", "", csp)
            if csp.strip():
                response.headers["content-security-policy"] = csp
            else:
                del response.headers["content-security-policy"]

        return response


app.add_middleware(AllowIframeMiddleware)

# Initialize NiceGUI frontend routes BEFORE mounting
init_frontend()

# Mount NiceGUI onto FastAPI (modifies app in place)
# This must happen at module level so Uvicorn can import 'main:app'
ui.run_with(
    app,
    title="Rubric AI",
    favicon="favicon.png",
    storage_secret=settings.SUPABASE_ANON_KEY or "rubric-ai-secret",
    mount_path="/",
    reconnect_timeout=10,  # Handle HF Spaces proxy timeouts
)


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(
        "main:app",
        host=settings.HOST,
        port=settings.PORT,
        reload=True,
    )