Muposat
Muposat

Reputation: 1506

Cannot unpack request JSON with CSRF on

Ajax request can be unpacked as long as @csrf.exempt is set. As soon as I comment it out, request.get_json(force=True) fails. Putting it through debugger: (Pdb) p request._cached_json 'Request' object has no attribute '_cached_json' Template code:

var csrf_token = "{{ csrf_token() }}";
$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", csrf_token);
        }}});

Dispatching the request:

save()
{
    $.post("/save", JSON.stringify({'name': 'aaa'}), accept_reply, "json");
} 

Flask processing request:

@app.route('/save', methods=("POST",))
#@csrf.exempt
def save():
    order_data = request.get_json(force=True)
    return jsonify({"status": "ok"})

When @csrf.exempt is commented out, request has no attribute _cached_json: request.get_json(force=True) raises exception, while request.get_json() simply returns None.

Upvotes: 0

Views: 89

Answers (1)

abigperson
abigperson

Reputation: 5362

The issue here is that Flask requires a "Content-Type": "application/json" header to recognized that you are posting a JSON package, otherwise I believe it thinks you're sending urlencoded form data.

I've found that I can't use any jQuery "convenience" AJAX methods if I am looking to POST JSON data to Flask.

Try this:

$.ajax({
    type: "POST",
    url: "{{ url_for('.update_formulary_mb') }}",
    contentType: "application/json",
    data: JSON.stringify({id: state.config, update: records}),
    dataType: "json",
    success: function(response) {
        console.log(response);
    },
    error: function(err) {
        console.log(err);
    },
});

Edit 9/1/2017

As it turns out you can use jQuery post() method if all of your XHR requests require the same parameters using jQuery's ajaxSetup() method:

$.ajaxSetup({
    contentType: "application/json"
});

This will pass common parameters to all ajax and derivative methods within the scope of it's use... so it works well if you're following the same pattern in all of your XHR calls on a page...

Upvotes: 1

Related Questions