Replies: 4 comments 8 replies
-
|
The MRE is unnecessarily complex. You can showcase this without sub-router |
Beta Was this translation helpful? Give feedback.
This comment has been hidden.
This comment has been hidden.
-
MREHere is a MRE implemented in form of test (in the details): Detailsimport pytest
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from starlette.testclient import TestClient
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.exception_handler(Exception)
async def exception_handler(request, ex):
return JSONResponse(content={"success": False})
@app.exception_handler(AssertionError)
# @app.exception_handler(ValueError) # <= Uncommenting this line will make both tests pass
async def value_error_exception_handler(request, ex):
return JSONResponse(content={"success": False})
@app.post("/test1")
async def ep_1():
assert "a" == "b"
@app.post("/test2")
async def ep_2():
raise ValueError("Invalid value")
@pytest.mark.parametrize(
"url",
[
"/test1",
"/test2",
],
)
def test_cors_headers(url: str):
headers = {
"Origin": "https://localhost.tiangolo.com",
"Access-Control-Request-Method": "GET",
"Access-Control-Request-Headers": "X-Example",
}
client = TestClient(app, raise_server_exceptions=False)
resp = client.post(url, headers=headers)
assert resp.status_code == 200
assert "access-control-allow-origin" in resp.headersWhat is happening here:
Why this is happeningThis is because And, as your response is sent by outer-most middleware ( If you want to make your exception handled by So, this is why setting the exception handler for SolutionThe fact that Detailsimport pytest
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from starlette.testclient import TestClient
app = FastAPI()
@app.exception_handler(Exception)
async def exception_handler(request, ex):
return JSONResponse(content={"success": False})
@app.exception_handler(AssertionError)
async def value_error_exception_handler(request, ex):
return JSONResponse(content={"success": False})
@app.post("/test1")
async def ep_1():
assert "a" == "b"
@app.post("/test2")
async def ep_2():
raise ValueError("Invalid value")
# Important to wrap our app by CORSMiddleware after adding all endpoints and exception handlers
app = CORSMiddleware(
app=app,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@pytest.mark.parametrize(
"url",
[
"/test1",
"/test2",
],
)
def test_cors_headers(url: str):
headers = {
"Origin": "https://localhost.tiangolo.com",
"Access-Control-Request-Method": "GET",
"Access-Control-Request-Headers": "X-Example",
}
client = TestClient(app, raise_server_exceptions=False)
resp = client.post(url, headers=headers)
assert resp.status_code == 200
assert "access-control-allow-origin" in resp.headers |
Beta Was this translation helpful? Give feedback.
-
|
Hi~ @xdewx |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
the MRE is at https://github.com/4tst/mre-exception-handler.
without
@exception_handler(ValueError), then will appear CORS error when router raise ValueError,for more detail, please click here
What's actually bothering me is FastAPI's error handling mechanism—why does it allow middleware to cause counterintuitive issues? Besides going to the trouble of understanding the internal mechanics, can FastAPI avoid such problems in a more elegant and intuitive way?
Beta Was this translation helpful? Give feedback.
All reactions