[Flask] flask and jquery/ajax

Scott Woodstock sidwoodstock at gmail.com
Wed Jan 22 15:48:10 EST 2020


I ran into something similar a couple months ago. If you're facing the same
thing, it's because your server is expecting a CSRF token. Simply attaching
the token via $.ajaxSetup is what I used first but then found that tokens
expire so if I had the page open too long it'd start returning 400 bad
request again. Ultimately I added a heartbeat with a flask endpoint to
refresh it.

    var csrf_token = '{{ csrf_token() }}';
    // refresh the csrf token every 30 minutes
    var heartbeat = setInterval(function () {
      $.ajax({
        url: '{{ url_for('csrf_refresh') }}',
        type: 'GET',
        headers:{
          // attach csrf token
          'X-CSRFToken': csrf_token
        },
        success: function (response) {
          csrf_token = response;
        },
        error: function (jqXHR, textStatus, errorThrown) {
          console.log(jqXHR, textStatus, errorThrown);
          alert('Connection with server lost! Please refresh the page.')
        },
        dataType: "json",
        contentType: "application/json"
      });
    }, 30 * 60 * 1000);


    // apply the csrf token before each request
    $.ajaxSetup({
      beforeSend: function(xhr, settings) {
        if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) &&
!this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", csrf_token);  // insert
custom header
        }
      },
    });

and then the flask route to get a new CSRF token:

@app.route('/tools/_refresh_csrf/', methods=['GET'])
@roles_accepted('admin', 'copy', 'client')
def csrf_refresh():
    try:
        validate_csrf(request.headers.get('X-CSRFToken'))
        new_token = generate_csrf()
        return jsonify(new_token)
    except ValidationError:
        abort(400)

On Wed, Jan 22, 2020 at 9:03 AM <flask-request at python.org> wrote:

> Send Flask mailing list submissions to
>         flask at python.org
>
> To subscribe or unsubscribe via the World Wide Web, visit
>         https://mail.python.org/mailman/listinfo/flask
> or, via email, send a message with subject or body 'help' to
>         flask-request at python.org
>
> You can reach the person managing the list at
>         flask-owner at python.org
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of Flask digest..."
>
>
> Today's Topics:
>
>    1. flask and jquery/ajax (Corey Boyle)
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Wed, 22 Jan 2020 10:34:28 -0500
> From: Corey Boyle <coreybrett at gmail.com>
> To: flask <flask at python.org>
> Subject: [Flask] flask and jquery/ajax
> Message-ID:
>         <CAD=ssw3j5=Cxif3Rcez6MoDX8f=
> hYpFpPV7dH8WVD0wtYpMd4g at mail.gmail.com>
> Content-Type: text/plain; charset="UTF-8"
>
> I have a button on a webpage that I would like to trigger a function
> on the server.
>
> Example that works...
>
> JS
>
> <script>
> $(function() {
> $('#customers').on('click', '.markfocus', function() {
> $.get("{{url_for('sales_ajax.focus_customer')}}", {cpk:
> $(this).data("cpk")}, function(data) {});
> });
>
> //$(this).hide();
> return false;
> });
>
> </script>
>
> Python3
>
> @ajax.route('/focus_customer', methods=GP)
> def focus_customer():
> cpk = request.args.get('cpk', 0, type=int)
> if cpk:
>   customer = m.Customer.query.get_or_404(cpk)
>   yadayadayada
>   db.session.add(customer)
>   db.session.commit()
>
> return jsonify(result='ok')
>
> However, I know I shouldn't be using GET to make changes in my
> database, so I am trying to convert the above into a POST request.
>
> I've tried...
>
> JS
>
> <script>
> $(function() {
> $('#customers').on('click', '.markfocus', function() {
> $.ajax({
> url:"{{url_for('sales_ajax.focus_customer')}}",
> type:"POST",
> data:{ 1:1 },
> contentType:"application/json; charset=utf-8",
> dataType:"json",
> success: function(){}
> });
>
> //$(this).hide();
> return false;
> });});
>
> </script>
>
> Python3
>
> @ajax.route('/focus_customer', methods=GP)
> def focus_customer():
> print(request.data)
> print(request.json)
> return jsonify(result='ok')
>
> But, I get a 400 bad request message.
> If I comment out the "print(request.json)" line, I get "b'1=1'" on the
> terminal.
>
> What am I missing here?
>
>
> ------------------------------
>
> Subject: Digest Footer
>
> _______________________________________________
> Flask mailing list
> Flask at python.org
> https://mail.python.org/mailman/listinfo/flask
>
>
> ------------------------------
>
> End of Flask Digest, Vol 55, Issue 1
> ************************************
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/flask/attachments/20200122/f3159070/attachment.html>


More information about the Flask mailing list