How to Configure CORS Settings for Cross-Origin Requests in the FastAPI Backend

To configure CORS in the MathModelAgent FastAPI backend, set the CORS_ALLOW_ORIGINS environment variable in your .env file, and the CORSMiddleware registered in backend/app/main.py will automatically apply these settings to allow or restrict cross-origin requests.

The jihe520/mathmodelagent repository implements a centralized configuration approach for cross-origin resource sharing (CORS) that separates environment-specific settings from application logic. This architecture allows you to control which frontend origins can communicate with your backend API without modifying source code.

Understanding the CORS Architecture

The MathModelAgent backend uses FastAPI's built-in CORSMiddleware to handle cross-origin requests. The configuration flows through three distinct layers:

  1. Environment Layer: The .env.dev (or production .env) file stores the raw CORS_ALLOW_ORIGINS string
  2. Settings Layer: backend/app/config/setting.py parses the environment variable into a Python list using a custom Pydantic validator
  3. Application Layer: backend/app/main.py registers the middleware with the processed settings

This separation ensures that sensitive origin URLs remain environment-specific while maintaining type safety through Pydantic validation.

Step-by-Step CORS Configuration

Configure Environment Variables

Create or edit the environment file at the repository root. For development, use .env.dev:


# backend/.env.dev

CORS_ALLOW_ORIGINS=http://localhost:5173,http://localhost:3000

The value accepts a comma-separated list of origins. To allow all origins during development (the default), use:

CORS_ALLOW_ORIGINS=*

Validate Settings Configuration

The backend/app/config/setting.py file contains the Settings class that processes the environment variable. At line 44, the CORS_ALLOW_ORIGINS field uses a custom parse_cors validator to transform the comma-separated string into a Python list:


# backend/app/config/setting.py (excerpt)

from pydantic import field_validator
from typing import List

class Settings(BaseSettings):
    CORS_ALLOW_ORIGINS: List[str] = ["*"]
    
    @field_validator("CORS_ALLOW_ORIGINS", mode="before")
    @classmethod
    def parse_cors(cls, value):
        if isinstance(value, str):
            return [origin.strip() for origin in value.split(",") if origin.strip()]
        return value

This validator ensures that http://localhost:5173,http://localhost:3000 becomes ["http://localhost:5173", "http://localhost:3000"] before reaching the middleware.

Register Middleware

In backend/app/main.py, lines 38–45 instantiate the CORSMiddleware using the parsed configuration:


# backend/app/main.py

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.config.setting import settings

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.CORS_ALLOW_ORIGINS,  # Parsed from env variable

    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
    expose_headers=["*"],
)

The allow_origins parameter receives the list directly from settings.CORS_ALLOW_ORIGINS, ensuring your environment configuration controls access.

Practical Configuration Examples

Restrict to Production Domains

For a production deployment serving a specific frontend, set the environment variable to explicit domains:

CORS_ALLOW_ORIGINS=https://app.example.com,https://admin.example.com

No code changes are required; restart the FastAPI server to apply the restrictions.

Disable Credentials for Public APIs

If your MathModelAgent instance serves public data without authentication, modify the middleware parameters in backend/app/main.py:

app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.CORS_ALLOW_ORIGINS,
    allow_credentials=False,  # Disable cookie transmission

    allow_methods=["GET", "OPTIONS"],  # Read-only access

    allow_headers=["Content-Type"],
)

Dynamic Runtime Configuration

For scenarios requiring runtime origin calculation (e.g., multi-tenant setups), modify the settings during the startup event:

@app.on_event("startup")
async def configure_cors():
    # Dynamically fetch allowed origins from database or external service

    tenant_origins = ["https://tenant1.com", "https://tenant2.com"]
    settings.CORS_ALLOW_ORIGINS = tenant_origins

Ensure this executes before the first request arrives, as middleware configuration is baked at application startup.

Advanced CORS Customization

Beyond origin restrictions, the MathModelAgent implementation exposes standard FastAPI CORS parameters:

  • allow_methods: Limit HTTP verbs (e.g., ["GET", "POST"] vs ["*"])
  • allow_headers: Specify permitted headers like ["Authorization", "Content-Type"]
  • expose_headers: Make custom response headers visible to the frontend
  • max_age: Cache preflight responses (default varies by browser)

These parameters reside in backend/app/main.py alongside the origin configuration.

Summary

  • Environment-driven: Set CORS_ALLOW_ORIGINS in .env.dev or production .env files to control access without code changes
  • Validated parsing: The parse_cors validator in backend/app/config/setting.py (line 44) converts comma-separated strings to lists
  • Middleware integration: backend/app/main.py (lines 38–45) registers CORSMiddleware using the processed settings object
  • Default permissive: The repository defaults to ["*"] (all origins) for development convenience
  • Type safety: Pydantic ensures the CORS_ALLOW_ORIGINS field always resolves to a List[str]

Frequently Asked Questions

How do I allow all origins during development?

Set CORS_ALLOW_ORIGINS=* in your .env.dev file. The parse_cors validator in backend/app/config/setting.py converts this to ["*"], which FastAPI interprets as allowing all origins. Remove or override this in production environments to prevent security vulnerabilities.

Where is the CORS configuration validated?

Validation occurs in backend/app/config/setting.py within the Settings class. The parse_cors method (referenced at line 44) ensures that string inputs from environment variables become properly formatted Python lists before the application initializes the middleware.

Can I restrict specific HTTP methods while keeping open origins?

Yes. While origins are controlled via the environment variable, HTTP methods are hardcoded in backend/app/main.py. Modify the allow_methods parameter in the CORSMiddleware instantiation to restrict verbs (e.g., change ["*"] to ["GET", "POST"]) while keeping allow_origins permissive.

Why are my CORS changes not taking effect?

FastAPI loads middleware configuration at application startup. After modifying .env.dev or environment variables, you must restart the Uvicorn server. Additionally, verify that your environment file is actually loaded—check that backend/app/config/setting.py points to the correct env file path in its model_config or Config class definition.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →