corydolphin / flask-cors

Cross Origin Resource Sharing ( CORS ) support for Flask
https://flask-cors.corydolphin.com/
MIT License
867 stars 140 forks source link

CORS issue #346

Open SnowPatrolXV opened 3 months ago

SnowPatrolXV commented 3 months ago

Hi,

I am developing a web app with a frontend in react (http://localhost:5173/) and a backend in Flask (http://localhost:5000/).

The simple requests (GET, POST and OPTIONS) work perfectly. But, the complex requests (PUT and DELETE) are refused by the backend (405 - METHOD NOT ALLOWED).

the Flask-CORS logging is enable and in the the trace of the backend, the OPTIONS request and the PUT request.

127.0.0.1 - - [27/Mar/2024 17:03:03] "OPTIONS /measures HTTP/1.1" 200 -
Request to '/measures' matches CORS resource '/*'. Using options: {'origins': ['http://127.0.0.1:5173', 'http://localhost:5173'], 'methods': 'DELETE, GET, OPTIONS, POST, PUT', 'allow_headers': ['Authorization', 'Content-Type'], 'expose_headers': None, 'supports_credentials': True, 'max_age': None, 'send_wildcard': False, 'automatic_options': True, 'vary_header': True, 'resources': {'/*': {'origins': ['http://127.0.0.1:5173', 'http://localhost:5173'], 'methods': ['OPTIONS', 'GET', 'POST', 'PUT', 'DELETE'], 'allow_headers': ['Authorization', 'Content-Type'], 'supports_credentials': True}}, 'intercept_exceptions': True, 'always_send': True}
CORS request received with 'Origin' http://localhost:5173
The request's Origin header matches. Sending CORS headers.
Settings CORS headers: MultiDict([('Access-Control-Allow-Origin', 'http://localhost:5173'), ('Access-Control-Allow-Credentials', 'true'), ('Vary', 'Origin')])
CORS have been already evaluated, skipping
127.0.0.1 - - [27/Mar/2024 17:03:03] "PUT /measures HTTP/1.1" 405 -

On the backend side, the Flask-CORS is enable with this code :

api_cors_config = {
    "origins": ["http://127.0.0.1:5173", "http://localhost:5173"],
    "methods": ["OPTIONS", "GET", "POST", "PUT", "DELETE"],
    "allow_headers": ["Authorization", "Content-Type"],
    "supports_credentials": True,
}
CORS(app,resources={r'/*': api_cors_config})

The function which process the PUT request

@measures_bp.route("/<measure_id>", methods=["PUT"])
@cross_origin()
def update_measure(measure_id):
    existing_measure = Measure.query.get(measure_id)
    existing_measure.name = request.json['name']
    existing_measure.coverage = request.json['coverage']
    db.session.commit()

    response = Response(status=204)
    return response

On the frontend, the request is sent by this code

fetch('http://127.0.0.1:5000/measures',
{
  mode: 'cors',
  method: 'PUT',
  headers: {
    'Content-type': 'application/json',
    'Origin' : 'http://localhost:5173',
    'Access-Control-Request-Method' : 'PUT',
    'Access-Control-Request-Headers' : 'Authorization, Content-Type',
  },
  body: JSON.stringify({
    measure_id: item.id,
    name: row.name,
    maturity_id : null,
    coverage: row.coverage
  }),
})

From my understanding, the issue comes from the Options request. The Allow header of the response does not have the PUT and DELETE METHOD. Access-Control-Allow-Headers: content-type Access-Control-Allow-Methods: DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT Access-Control-Allow-Origin: http://localhost:5173 Allow: HEAD, GET, POST, OPTIONS

In the documentation, I do not see how to overide or config the Allow header.

Have-you an idea how to fix this issue ?