1010from uuid import uuid4
1111
1212from fastapi import APIRouter , HTTPException , Request , Depends , Header
13+ from fastapi .middleware .cors import CORSMiddleware
1314from fastapi .responses import FileResponse
1415
1516# Global results directory inside project root
@@ -512,6 +513,38 @@ def to_bool(val, default=False):
512513 raise HTTPException (status_code = 500 , detail = str (e ))
513514
514515
516+ # Origins that are expected to call the API:
517+ # - "null" → studio.html opened via file:// protocol
518+ # - http://localhost:* → local dev servers / Gradio UI
519+ # - http://127.0.0.1:* → same, numeric form
520+ _CORS_KWARGS = dict (
521+ allow_origins = ["null" , "http://localhost" , "http://127.0.0.1" ],
522+ allow_origin_regex = r"^https?://(localhost|127\.0\.0\.1)(:\d+)?$" ,
523+ allow_methods = ["GET" , "POST" , "OPTIONS" ],
524+ allow_headers = ["Content-Type" , "Authorization" ],
525+ )
526+
527+
528+ def _add_cors_middleware (app ):
529+ """Add CORS middleware so browser-based frontends (e.g. studio.html via file://) can call the API."""
530+ app .add_middleware (CORSMiddleware , ** _CORS_KWARGS )
531+
532+
533+ def _add_cors_middleware_post_launch (app ):
534+ """Wrap an already-started app's middleware stack with CORS.
535+
536+ ``add_middleware`` raises after Starlette has started, so we patch the
537+ compiled middleware stack directly instead.
538+ """
539+ from starlette .middleware .cors import CORSMiddleware as _CORSImpl
540+
541+ if app .middleware_stack is not None :
542+ app .middleware_stack = _CORSImpl (app = app .middleware_stack , ** _CORS_KWARGS )
543+ else :
544+ # App hasn't built its stack yet – safe to use the normal path
545+ _add_cors_middleware (app )
546+
547+
515548def setup_api_routes_to_app (app , dit_handler , llm_handler , api_key : Optional [str ] = None ):
516549 """
517550 Mount API routes to a FastAPI application (for use with gr.mount_gradio_app)
@@ -523,6 +556,7 @@ def setup_api_routes_to_app(app, dit_handler, llm_handler, api_key: Optional[str
523556 api_key: Optional API key for authentication
524557 """
525558 set_api_key (api_key )
559+ _add_cors_middleware (app )
526560 app .state .dit_handler = dit_handler
527561 app .state .llm_handler = llm_handler
528562 app .include_router (router )
@@ -540,6 +574,7 @@ def setup_api_routes(demo, dit_handler, llm_handler, api_key: Optional[str] = No
540574 """
541575 set_api_key (api_key )
542576 app = demo .app
577+ _add_cors_middleware_post_launch (app )
543578 app .state .dit_handler = dit_handler
544579 app .state .llm_handler = llm_handler
545580 app .include_router (router )
0 commit comments