Flask and Ajax Post HTTP 400 Bad Request Error Flask and Ajax Post HTTP 400 Bad Request Error flask flask

Flask and Ajax Post HTTP 400 Bad Request Error


If you are using the Flask-WTF CSRF protection you'll need to either exempt your view or include the CSRF token in your AJAX POST request too.

Exempting is done with a decorator:

@csrf.exempt@app.route("/json_submit", methods=["POST"])def submit_handler():    # a = request.get_json(force=True)    app.logger.log("json_submit")    return {}

To include the token with AJAX requests, interpolate the token into the page somewhere; in a <meta> header or in generated JavaScript, then set a X-CSRFToken header. When using jQuery, use the ajaxSetup hook.

Example using a meta tag (from the Flask-WTF CSRF documentation):

<meta name="csrf-token" content="{{ csrf_token() }}">

and in your JS code somewhere:

var csrftoken = $('meta[name=csrf-token]').attr('content')$.ajaxSetup({    beforeSend: function(xhr, settings) {        if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type)) {            xhr.setRequestHeader("X-CSRFToken", csrftoken)        }    }})

Your handler doesn't actually post JSON data yet; it is still a regular url-encoded POST (the data will end up in request.form on the Flask side); you'd have to set the AJAX content type to application/json and use JSON.stringify() to actually submit JSON:

var request = $.ajax({   url: "/json_submit",   type: "POST",   contentType: "application/json",   data: JSON.stringify({     id: id,      known: is_known   }),  })    .done( function (request) {})

and now the data can be accessed as a Python structure with the request.get_json() method.

The dataType: "json", parameter to $.ajax is only needed when your view returns JSON (e.g. you used flask.json.jsonify() to produce a JSON response). It lets jQuery know how to process the response.


Can you try like this

var request = $.ajax({    url: "/json_submit",    type: "POST",    contentType: "application/json",    data: JSON.stringify({      id: id,       known: is_known    }),      dataType: "json",  })     .done( function (request) { })

Before that, In your code returns dict object. That is not correct. It returns json like

@app.route("/json_submit", methods=["POST"])def submit_handler():    # a = request.get_json(force=True)    app.logger.log("json_submit")    return flask.jsonify({'msg': 'success'})


A similar solution that does not require jQuery

<meta name="csrf-token" content="{{ csrf_token() }}">var beforeSend = function(xhr) {    var csrf_token = document.querySelector('meta[name=csrf-token]').content;    xhr.setRequestHeader("X-CSRFToken", csrf_token);};function fooFunction() {    var xhr = new XMLHttpRequest();    xhr.open("POST", "/json-submit");    xhr.onreadystatechange = function() {        if (this.readyState == 4 && this.status == 200) {            // Do what you want with this.responseText        }    };    beforeSend(xhr);    xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");    xhr.send(JSON.stringify({        'id': id, 'known': is_known    }));};