Search code examples
pythontypescriptflaskcorsvscode-restclient

Axios POST causes CORS error despite enabling CORS in Flask


I have spent many days on this problem and still couldn't figure out how to solve this. I'm having CORS issues and I've tried enabling CORS in Flask but it didn't work.

Backend code (hosted on port 5000):

from flask import Flask, request, jsonify
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/process", methods=['POST'])
def process():
    print('process')
    # process here
    return jsonify({'response': 'OK'})

Frontend code (hosted on port 3001. I use react, only the function that sends the request shown here):

import axios from 'axios';
import FormData from 'form-data';

const sendFile = (binary: ArrayBuffer) => {
    console.log('sending file');
    const formData = new FormData();
    formData.append('image', new Blob([binary]), file.name);

    const options = {
        method: 'POST',
        url: 'http://localhost:5000/process',
        // url: 'https://postman-echo.com/post',
        data: formData,
    };
    axios(options)
        .then(response => {
            console.log(response);
        })
        .catch(error => {
            console.error(error);
        });
};

Error as shown in Chrome console:

Access to XMLHttpRequest at 'http://localhost:5000/process' from origin 'http://localhost:3001' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

and

POST http://localhost:5000/process net::ERR_FAILED 403 (Forbidden)


I also tested with VSCode REST Client using this request:

POST http://localhost:5000/process
Content-Type: multipart/form-data; boundary=your-unique-boundary

--your-unique-boundary
Content-Disposition: form-data; name="image"; filename="IMG_6651.PNG"
Content-Type: image/png

< /Users/johan/Downloads/IMG_6651.PNG
--your-unique-boundary--

It worked using the REST client so the backend is running properly. But I guess the REST client doesn't follow SOP. So I tried to see if it does return with Access-Control-Allow-Origin header and it does:

% curl -I -X POST http://localhost:5000/process
HTTP/1.1 200 OK
Server: Werkzeug/2.2.2 Python/3.10.8
Date: Fri, 01 Dec 2023 09:37:22 GMT
Content-Type: application/json
Content-Length: 23
Access-Control-Allow-Origin: *
Connection: close

Questions:

  1. I thought I already allow CORS using flask_cors but it didn't work. How do I solve this?
  2. Am I sending the same format of requests in my frontend and in VSCode REST client? If not, what's the equivalent frontend code of the request in REST client?
  3. From the curl response, it seems Access-Control-Allow-Origin header is indeed included, then why do I still get CORS issues?
  4. Is the 403 error a result of the CORS issue? Do I have two problems or one problem here?
  5. I'm sending a simple request, which means there's no preflight request, correct?

Solution

  • I wasted so much time on this. I suspect it's some problem in flask-cors. As I just started, I decided to switch to FastAPI instead and it fixed the CORS issue immediately.

    app = FastAPI()
    origins = [
        '*',
    ]
    app.add_middleware(
        CORSMiddleware,
        allow_origins=origins,
    )
    
    @app.post("/process") 
    async def process(image: UploadFile = File(...)):
        print('process') 
        # process here
        return JSONResponse({"response": "OK"})