-1

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

Brian L
  • 549
  • 7
  • 21

2 Answers2

1

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

Brian L
  • 549
  • 7
  • 21
0

backend code running on different port you can use * or defined an all port that use on your app

origins = [
    "http://localhost:*",
    "http://localhost:3000",
    "http://127.0.0.1:8000",
]
Mr Coder
  • 507
  • 3
  • 13
  • Nope, adding the wildcard does not seem to help, this produces the same error – Brian L Feb 25 '20 at 15:30
  • your application run on a different port check that – Mr Coder Feb 25 '20 at 15:36
  • My frontend runs on http://localhost:3000 and my backend runs on http://127.0.0.1:8000, both of which are included in origins. You will also note that the code runs when you do not call yaml.load() on the same endpoint, so it is probably nothing to do with the endpoint, it is likely something to do with some redirection when calling yaml.load() – Brian L Feb 25 '20 at 15:43
  • also error and code header show it 307 redirects so the path was wrong something checks into your code. open console network and see where is request going – Mr Coder Feb 25 '20 at 15:52
  • If the path is wrong why would it work when I dont run the yaml.load() line in the backend? – Brian L Feb 25 '20 at 16:18