2016-07-09 2 views
0

In meiner Flask-App versuche ich POST-Anfrage über AJAX-Aufruf zu implementieren, wenn der Benutzer auf den Link klickt. Es funktioniert wie ein Charme in Chrom. Ich habe keine Probleme, wenn meine Ansicht Funktion durch httpie Beantragung entweder:POST-Anfrage über AJAX führt zu Fehler 404 in Firefox nur

$ http --json POST http://127.0.0.1:5000/ctrl/remove-category id=1 csrf=1 

(venv) $ : http --json POST http://127.0.0.1:5000/ctrl/remove-category id=5 csrf=1 
HTTP/1.0 200 OK 
Content-Length: 78 
Content-Type: application/json 
Date: Sat, 09 Jul 2016 09:05:20 GMT 
Server: Werkzeug/0.11.8 Python/3.5.1 

{ 
    "message": "Category 'test 5' has been removed", 
    "status": "success" 
} 

Aber in Firefox geschieht etwas Seltsames. Ich habe es unter zwei FF-Profilen getestet. Beide geben mir 404 Fehler. Wenn ich auf den Link unter meinem ersten FF-Profil klicke, bekomme ich 404 und nichts passiert, d. H. Ich sehe keine POST-Anfrage an Werkzeug-Server, nur GET-Anfrage.

Unter dem zweiten FF-Profil habe ich noch einen Fehler in der Firebug-Konsole erhalten:

POST http://127.0.0.1:5000/ctrl/remove-category 31ms  jquery.min.js (line 6) 
Error code: 404            categories (line 455) 

So POST-Anfrage gesendet wird, und ich sehe es in meinem Werkzeug Protokolle:

127.0.0.1 - - [09/Jul/2016 11:29:11] "POST /ctrl/remove-category HTTP/1.1" 200 - 
127.0.0.1 - - [09/Jul/2016 11:29:12] "GET /ctrl/categories HTTP/1.1" 200 - 

, dennoch habe ich noch bekomme keine anderen Dinge in meinem AJAX `.success 'Aufruf (wie Dinge in localStorage, etc. zu speichern)

Hier ist mein jQuery Skript:

<script> 
$('.remove').click(function() { 
    var data = {}; 
    data['csrf'] = $('#csrf-removal').val() 
    data['id'] = $(this).data('id-removal'); 

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

    var remove = confirm('Are you sure?'); 
    if (remove == true) { 
    $.ajax({ 
      url: "{{ url_for('ctrl.remove_category', _external=True) }}", 
      type: 'post', 
      dataType: 'json', 
      contentType: 'application/json;charset=UTF-8', 
      data: JSON.stringify(data, null, '\t'), 
     success: function(response) { 
     // message to user 
     var flash = "<div class='alert alert-" + response['status'] + "'>" + 
        "<button type='button' class='close' data-dismiss='alert'>&times;</button>" + 
        response['message'] + "</div>"; 
     // save message to localStorage 
     window.onbeforeunload = function() { 
      localStorage.setItem('message', flash); 
     } 
     // reload the page 
     location.reload(); 
     // jump to the top of the page 
     $('html,body').scrollTop(0); 
      }, 
      error: function(jqXHR, textStatus, errorThrown) { 
     console.log('Error code: ' + jqXHR.status); 
      } 
    }); 
    } 
}); 
</script> 

Dies ist meine Ansicht nach Funktion:

@csrf.exempt # for httpie testing 
@ctrl.route('/remove-category', methods=['POST']) 
#@permission_required(Permission.ADMINISTER) # httpie testing 
def remove_category(): 
    try: 
     id = request.json['id'] 
     csrf = request.json['csrf'] 
    except KeyError: 
     return jsonify({ 
      'status': 'error', 
      'message': 'Function takes two parameters: ' 
         'id of the entry to be removed; csrf token', 
     }) 

    category = Category.query.get_or_404(id) 
    if category.posts.count(): 
     status = 'warning' 
     message = "Category '{0}' is not empty and cannot be removed".\ 
        format(category.title) 
    else: 
     status = 'success' 
     message = "Category '{0}' has been removed".\ 
        format(category.title) 
     db.session.delete(category) 
    return jsonify({ 
     'status': status, 
     'message': message, 
    }) 

Ich bin mit jQuery 2.0.3, Flask 0.10.1, Flask-WTF 0.9.4 und Firefox 47.0. Ich bin sehr neu zu Javascript und Cross-Browser-Dinge im Zusammenhang mit js, so dass jede Hilfe geschätzt wird.

P.S. Ich bin mir bewusst, , aber accepts mit 'Application/Json' in Ajax Aufruf nicht geholfen.

UPDATE: Mit DevTools in Chrom und Firebug in Firefox, ich POST-Anfragen von beiden Browsern wie cURL Befehle kopiert und ihre Ergebnisse miteinander verglichen:

  1. Chrom (siehe gist) wie erwartet funktioniert, Server bekommt eine Anfrage und sendet Antwort.

  2. Firefox (siehe gist) funktioniert nicht. Anfrage gesendet, aber keine Antwort erhalten. cURL' is hanging untill I terminate it with^C '. Nach Beendigung ich Protokolle sehen die Werkzeug Webserver gibt Fehler 400:

    127.0.0.1 - - [09/Aug/2016 14.29.01] "POST/ctrl/remove-Kategorie HTTP/1.1" 400

+0

Versuchen [RESTClient] (https://addons.mozilla.org/en-US/firefox/addon/restclient/) Addon für Firefox und sehen was du zurück bekommst. Möglicherweise müssen Sie selbst JSON schreiben. Beispiel: '{'id': '5', 'csrf': '1'}'. Wenn dies nichts anzeigt, versuchen Sie [Fiddler] (http://www.telerik.com/fiddler), um zu vergleichen, was sich an der Anfrage/Antwort zwischen Chrome und Firefox unterscheidet. – Miro

+0

@ Miro danke. Ich bin wohler mit Konsolen-Tools wie 'httpie' und' cURL' und vermute, dass sie die gleichen Funktionen 'RESTClient' haben. Ich kann 'Fiddler' jedoch nicht verwenden, wie es für Windows ist. Tatsächlich untersuchte ich beide Anfragen von FF und Chromium und aktualisierte meine Antwort. Ich habe immer noch keine Ahnung, was los ist – vrs

Antwort

0

Okay, ich habe das Problem gefunden.

Nach dem Lesen dieser bug report, habe ich auf jQuery 2.1.1 aktualisiert. Das führte dazu, Fehlercode 0 statt 404 zu erhalten. Statuscode 0 konnte bedeuten, dass mein Skript die Seite neu lädt, bevor es AJAX-Antwort (see this SO topic) erhält.

So habe ich setTimeout für 1 Sekunde Verzögerung, bevor die Seite neu zu laden:

setTimeout(function() { // wait 1 sec 
    location.reload(); // reload page 
    $('html,body').scrollTop(0); // jump on top 
}, 1000); 

Und das war der Trick.

P.S. setTimeout ist eine temporäre Problemumgehung, um zu sehen, ob es das Problem löst. Der richtige Weg, Dinge zu tun, wie das ist mit Versprechen (see jQuery.when/done)

Verwandte Themen