A Flask extension for handling Cross Origin Resource Sharing (CORS), making cross-origin AJAX possible
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
The cross_origin decorator provides route-specific Cross-Origin Resource Sharing configuration for individual Flask routes. It offers fine-grained control over CORS settings on a per-route basis with automatic OPTIONS request handling.
Decorator function that wraps Flask route handlers to enable CORS with configurable parameters. Applied directly to route functions for granular CORS control.
def cross_origin(
origins="*",
methods=None,
expose_headers=None,
allow_headers="*",
supports_credentials=False,
max_age=None,
send_wildcard=False,
vary_header=True,
automatic_options=True,
allow_private_network=False,
always_send=True,
**kwargs
):
"""
Decorator to enable CORS for specific Flask routes.
Parameters:
- origins: Allowed origins (string, list, or regex patterns)
- methods: Allowed HTTP methods (list or string)
- expose_headers: Headers safe to expose to CORS API (list or string)
- allow_headers: Headers allowed in requests (list, string, or regex)
- supports_credentials: Allow authenticated requests (bool)
- max_age: Cache time for preflight requests (timedelta, int, or string)
- send_wildcard: Send '*' instead of specific origin (bool)
- vary_header: Include Vary: Origin header (bool)
- automatic_options: Handle OPTIONS requests automatically (bool)
- allow_private_network: Allow private network access (bool, default: False)
- always_send: Send CORS headers even without Origin header (bool)
- **kwargs: Additional configuration options
Returns:
Decorated function with CORS headers applied
"""from flask import Flask
from flask_cors import cross_origin
app = Flask(__name__)
@app.route("/api/data")
@cross_origin() # Allow all origins with default settings
def get_data():
return {"message": "CORS-enabled data"}
@app.route("/api/public")
@cross_origin(origins="*") # Explicit wildcard
def public_endpoint():
return {"data": "public information"}from flask import Flask
from flask_cors import cross_origin
app = Flask(__name__)
@app.route("/api/secure")
@cross_origin(origins=["https://trusted-site.com", "https://app.example.com"])
def secure_endpoint():
return {"data": "restricted data"}
@app.route("/api/development")
@cross_origin(origins=["http://localhost:3000", "http://localhost:8080"])
def development_endpoint():
return {"data": "development data"}import re
from flask import Flask
from flask_cors import cross_origin
app = Flask(__name__)
@app.route("/api/subdomains")
@cross_origin(origins=r"https://.*\.example\.com")
def subdomain_endpoint():
return {"data": "subdomain accessible"}
@app.route("/api/pattern")
@cross_origin(origins=[
re.compile(r"https://app\d+\.example\.com"),
"https://main.example.com"
])
def pattern_endpoint():
return {"data": "pattern matched"}from flask import Flask, request
from flask_cors import cross_origin
app = Flask(__name__)
@app.route("/api/users", methods=["GET", "POST"])
@cross_origin(
origins=["https://frontend.example.com"],
methods=["GET", "POST"],
allow_headers=["Content-Type", "X-Requested-With"]
)
def users_endpoint():
if request.method == "GET":
return {"users": []}
elif request.method == "POST":
return {"created": True}from flask import Flask
from flask_cors import cross_origin
app = Flask(__name__)
@app.route("/api/auth/profile")
@cross_origin(
origins=["https://app.example.com"],
supports_credentials=True,
allow_headers=["Content-Type", "Authorization"]
)
def user_profile():
# This route accepts cookies and credentials
return {"profile": "user data"}
@app.route("/api/auth/login", methods=["POST"])
@cross_origin(
origins=["https://app.example.com"],
supports_credentials=True,
methods=["POST"]
)
def login():
return {"token": "auth-token"}from flask import Flask
from flask_cors import cross_origin
app = Flask(__name__)
@app.route("/api/upload", methods=["POST"])
@cross_origin(
origins=["https://uploader.example.com"],
allow_headers=["Content-Type", "X-File-Name", "X-Upload-Key"],
expose_headers=["X-Upload-ID", "X-Processing-Status"],
methods=["POST", "OPTIONS"]
)
def file_upload():
return {"upload_id": "12345", "status": "processing"}from datetime import timedelta
from flask import Flask
from flask_cors import cross_origin
app = Flask(__name__)
@app.route("/api/heavy-operation", methods=["POST"])
@cross_origin(
origins=["https://client.example.com"],
max_age=timedelta(hours=1), # Cache preflight for 1 hour
methods=["POST"]
)
def heavy_operation():
# Expensive operation that benefits from preflight caching
return {"result": "computed"}
@app.route("/api/frequent-calls")
@cross_origin(
origins=["https://dashboard.example.com"],
max_age=3600, # Cache for 1 hour (seconds)
allow_headers=["Content-Type", "Authorization"]
)
def frequent_endpoint():
return {"data": "frequently accessed"}from flask import Flask, jsonify
from flask_cors import cross_origin
app = Flask(__name__)
@app.route("/api/custom-options", methods=["GET", "POST", "OPTIONS"])
@cross_origin(
origins=["https://custom.example.com"],
automatic_options=False # Handle OPTIONS manually
)
def custom_options_endpoint():
if request.method == "OPTIONS":
# Custom preflight response
return jsonify({"preflight": "custom response"})
elif request.method == "GET":
return {"data": "get response"}
elif request.method == "POST":
return {"data": "post response"}from flask import Flask
from flask_cors import cross_origin
app = Flask(__name__)
@app.route("/api/complex")
@cross_origin(
origins=[
"https://prod.example.com", # Production
"https://staging.example.com", # Staging
r"https://.*\.dev\.example\.com", # Development subdomains
"http://localhost:3000" # Local development
],
methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=[
"Content-Type",
"Authorization",
"X-API-Key",
r"X-Custom-.*" # Regex pattern for custom headers
],
expose_headers=["X-Total-Count", "X-Rate-Limit-Remaining"],
supports_credentials=True,
max_age=1800, # 30 minutes
vary_header=True
)
def complex_endpoint():
return {"data": "complex CORS configuration"}The cross_origin decorator works seamlessly with other Flask extensions:
from flask import Flask
from flask_login import login_required
from flask_cors import cross_origin
app = Flask(__name__)
@app.route("/api/protected")
@cross_origin(
origins=["https://app.example.com"],
supports_credentials=True
)
@login_required
def protected_endpoint():
return {"data": "protected resource"}from flask import Flask
from flask_restful import Api, Resource
from flask_cors import cross_origin
app = Flask(__name__)
api = Api(app)
class UserResource(Resource):
@cross_origin(origins=["https://api-client.example.com"])
def get(self, user_id):
return {"user_id": user_id}
@cross_origin(
origins=["https://admin.example.com"],
methods=["POST"],
supports_credentials=True
)
def post(self):
return {"created": True}
api.add_resource(UserResource, "/api/users/<int:user_id>")The decorator provides automatic error handling for common CORS scenarios:
max_age for frequently preflight-checked endpointsInstall with Tessl CLI
npx tessl i tessl/pypi-flask-cors