Method PUT is not allowed by Access-Control-Allow-Methods in preflight response FLASK CORS

Franrey Saycon picture Franrey Saycon · Nov 26, 2018 · Viewed 10.2k times · Source

GETs are working right. I can't seem to make PUT work and I fear POST is not working as well.

Kept on having the error

Access to XMLHttpRequest at '<...>' from origin 'https://localhost:3000' has been blocked by CORS policy: Method PUT is not allowed by Access-Control-Allow-Methods in preflight response.

I have a local webapp that calls on an external api which means CORS will be one of the hurdles I should tackle.

Here's my flask code.

@blueprint.route('/profiles/<oi_id>', methods=['POST'])
@cross_origin(send_wildcard=True, methods=['POST', 'OPTIONS'])
def create_checkin_profile(oi_id):
    return jsonify(cph.create_owner_profile_info(oi_id, json.loads(request.data)))


@blueprint.route('/profiles/<oi_id>', methods=['PUT'])
@cross_origin(send_wildcard=True, methods=['PUT', 'OPTIONS'])
def edit_checkin_profile(oi_id):
    return jsonify(cph.edit_owner_profile_info(oi_id, json.loads(request.data)))

It's quite confusing since I'm pretty sure I allowed PUT. I'm using axios for this on a react app. Here's my call-api function.

axios({
      method: 'PUT',
      url: url,
      timeout: 3000,
      data: data,
      headers: {
        "Access-Control-Allow-Origin": "*",
        "Content-Type": "application/json",
        Accept: "application/json",
      },
    });

Answer

Franrey Saycon picture Franrey Saycon · Nov 27, 2018

Alright I fixed this. Apparently according to the docs I have to specify "Content-Type" on the cross origin requests. Like so:

@cross_origin(allow_headers=['Content-Type'])

Don't be fooled by the default of allow all. You need to specify this apparently.

I have to remove unnecessary headers such as Accept and Access-Control-Allow-Origin. Updating my axios like so:

axios({
    method: 'PUT',
    url: url,
    timeout: 3000,
    data: data,
    headers: {
        "Content-Type": "application/json",
    },
});

BONUS:

I ran into a problem if my api calls returned a non 200 response with preflight request, the response body becomes null. I just added these lines of code on my main application. I needed the body for the details of the error is there.

@app.after_request
def set_cors_header(response):
    response.headers['Access-Control-Allow-Origin'] = '*'
    return response