FastAPI: How to enable CORS only for specific endpoints?

Question:

The example below will enalbe CORS for all the endpoints in the application. How to enable CORS only for specific endpoints, or just an individual endpoint, using FastAPI?

from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=['*'],
    allow_credentials=False,
    allow_methods=["GET","DELETE"],
    allow_headers=["*"],
    max_age=0
)
Asked By: Hazem Alrfati

||

Answers:

You can create a Sub application with only the endpoints you wish to be accessible from a different origin than the backend, and add the CORSMiddleware to that sub app only.

Note that, as described in this answer, using the '*' wildcard in the allow_origins argument (as demonstrated in your question)—instead of specifying specific origins as demonstrated here—would mean that all origins are allowed; however, at the cost of excluding everything that involves credentials, such as cookies, authorization headers, etc; and hence, setting the allow_credentials argument to True (see Access-Control-Allow-Credentials response header documentation) would have no effect, and you still wouldn’t be able to send/receive credentials (such as those described above) between the client and the server, when a cross-origin request is performed (see here and here for more details).

Working Example

The /sub endpoint from subapi (sub application) in the example below can be accessed at http://127.0.0.1:8000/subapi/sub

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()
subapi = FastAPI()

# specify the origins from which you wish the backend (subapi) to be accessible 
origins = ['http://localhost:3000']  

subapi.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=['*'],
    allow_headers=['*'],
)


@app.get('/app')
def read_main():
    return {'message': 'Hello World from main app'}
    
 
@subapi.get('/sub')
def read_sub():
    return {'message': 'Hello World from sub API'}


app.mount('/subapi', subapi)
Answered By: Chris
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.