fastapi icon indicating copy to clipboard operation
fastapi copied to clipboard

HTTP_500_INTERNAL_SERVER_ERROR cause a CORS error on frontend

Open w-Bro opened this issue 3 years ago • 6 comments

First Check

  • [X] I added a very descriptive title to this issue.
  • [X] I used the GitHub search to find a similar issue and didn't find it.
  • [X] I searched the FastAPI documentation, with the integrated search.
  • [X] I already searched in Google "How to X in FastAPI" and didn't find any information.
  • [X] I already read and followed all the tutorial in the docs and didn't find an answer.
  • [X] I already checked if it is not related to FastAPI but to Pydantic.
  • [X] I already checked if it is not related to FastAPI but to Swagger UI.
  • [x] I already checked if it is not related to FastAPI but to ReDoc.

Commit to Help

  • [X] I commit to help with one of those options 👆

Example Code

all code is in Description

Description

It is hard to show all main code of my project, I would show part of my code below.

  1. I already processed CORS in fastapi, I am sure it work when axios request is successful.
app.add_middleware(
        CORSMiddleware,
        allow_origins=["*"],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
)
  1. My way to handle global exception is adding a middlware, and when my code raise a AttributeError by itself, frontend would get a CORS error and axios shows that error.response is undefined
@app.middleware('http')
    async def catch_exceptions_middleware(request: Request, call_next):
        try:
            return await call_next(request)
        except Exception as e:
            # from fastapi.responses import JSONResponse
            # from fastapi import status
            logger.debug(f"middware catch the error")
            return JSONResponse(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                content="Unknow Error"
            )

image

  1. But when I use exception_handler to catch the certain exception, there is no CORS error, and axios shows error.response successfully. Sadly, it cound not work well to catch all the other exception when i use @app.exception_handler(Exception)
@app.exception_handler(AttributeError)
    async def all_exception_handler(request: Request, exc: Exception):
        # from fastapi.responses import JSONResponse
        # from fastapi import status
        return JSONResponse(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            content="Unknow Error"
        )

image

  1. By all above, my question is , how cound I catch a global exception to ensure that there is no CORS error on frontend?

Operating System

Windows

Operating System Details

win10 uvicorn 0.15.0 starlette 0.16.0

FastAPI Version

0.70.0

Python Version

Python 3.7.10

Additional Context

No response

w-Bro avatar Oct 20 '21 09:10 w-Bro

It's starlette issue - https://github.com/encode/starlette/issues/1116

uriyyo avatar Oct 23 '21 12:10 uriyyo

It's starlette issue - encode/starlette#1116

yep, i had read it before i issued, i could not found a solution yet. And I still could not figure out that it was a bug or somethig, like feature?

w-Bro avatar Oct 25 '21 01:10 w-Bro

I believe it's a bug.

As a temporary workaround, you can add ServerErrorMiddleware middleware with global exc handler before all middlewares:

from starlette.middleware.errors import ServerErrorMiddleware
from starlette.requests import Request
from starlette.types import ASGIApp

from fastapi import FastAPI, status
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse


async def global_execution_handler(request: Request, exc: Exception) -> ASGIApp:
    return JSONResponse(
        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
        content="Unknown Error",
    )


app = FastAPI()
app.add_middleware(
    ServerErrorMiddleware,
    handler=global_execution_handler,
)
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

uriyyo avatar Oct 25 '21 11:10 uriyyo

I believe it's a bug.

As a temporary workaround, you can add ServerErrorMiddleware middleware with global exc handler before all middlewares:

from starlette.middleware.errors import ServerErrorMiddleware
from starlette.requests import Request
from starlette.types import ASGIApp

from fastapi import FastAPI, status
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse


async def global_execution_handler(request: Request, exc: Exception) -> ASGIApp:
    return JSONResponse(
        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
        content="Unknown Error",
    )


app = FastAPI()
app.add_middleware(
    ServerErrorMiddleware,
    handler=global_execution_handler,
)
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

thanks a lot, it works! Waiting for offical fixing.

w-Bro avatar Oct 26 '21 01:10 w-Bro

Had the same problem, thanks. Could someone please ping me once there will be an official fix?

tarasBilobran avatar Nov 06 '21 08:11 tarasBilobran

I believe it's a bug.

As a temporary workaround, you can add ServerErrorMiddleware middleware with global exc handler before all middlewares:

from starlette.middleware.errors import ServerErrorMiddleware
from starlette.requests import Request
from starlette.types import ASGIApp

from fastapi import FastAPI, status
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse


async def global_execution_handler(request: Request, exc: Exception) -> ASGIApp:
    return JSONResponse(
        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
        content="Unknown Error",
    )


app = FastAPI()
app.add_middleware(
    ServerErrorMiddleware,
    handler=global_execution_handler,
)
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

I think this workaround needs to be put into the fastapi official doc, as the starlette team ( here and here ) considers this is a feature, not a bug.

biaocy avatar Sep 08 '22 14:09 biaocy