Search code examples
pythoncorspyyamlfastapi

CORS error when using pyyaml with FastAPI


I am trying to create a simple web-application using a react front end and fastapi back end. One function of the web-app is the send a file that is collected at the front end and processed on the back end. I have an endpoint on the back end that looks like:

@app.post("/upload_file/")
async def create_upload_file(file: UploadFile = File(...)):
    for line in file.file.readlines():
        print(line)
    file.file.close()
    return {"filename": file.filename}

I have confirmed that this code works. From the front end I can send a file, watch the lines print out on my back end terminal, and the front end receives an http response with a 200 status code and the filename.

The issue comes when I try to use the pyyaml library to process the inbound yaml file. Below is a code snippet which does not work:

@app.post("/upload_file/")
async def create_upload_file(file: UploadFile = File(...)):
    yaml_data = yaml.load(file, Loader=yaml.FullLoader)
    return yaml_data

I get the error:

Access to XMLHttpRequest at 'http://127.0.0.1:8000/upload_file/' (redirected from 'http://127.0.0.1:8000/upload_file') from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

So this seems to be a CORS issue... My current CORS policy for FastAPI looks like:

origins = [
    "http://localhost",
    "http://localhost:3000",
    "http://127.0.0.1:8000",
]

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

Do I have to add something to my CORS policy to allow it to use pyyaml? I did not think that would be the case since the processing should still be done at the same endpoint (note the endpoints are at the same place), however CORS is clearly not happy about using that yaml.load() function. Any suggestions on being able to load yaml files in my back end would be much appreciated.

Per request from Rishabh Batra I have added the OPTIONS headers here: enter image description here


Solution

  • Solved it. Turns out for starlette, a library that FastAPI is built off, the UploadFile object is not analogous to the python file object. If you want it to behave like a python file object you have to do file.file. So for the above snippet which was failing, the correct way to do that would be like:

    @app.post("/upload_file/")
    async def create_upload_file(file: UploadFile = File(...)):
        yaml_data = yaml.load(file.file, Loader=yaml.FullLoader)
        return yaml_data
    

    CORS policy was correct, no idea why it was throwing a CORS error