2016-07-09 80 views
0

在我的Flask-app中,當用戶單擊鏈接時,嘗試通過AJAX調用實現POST請求。 它的作用就像鉻中的魅力。通過httpie要麼請求我的看法功能時,我沒有問題:通過AJAX的POST請求導致Firefox中的錯誤404僅

$ 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" 
} 

,但在Firefox奇怪的事情發生。我在兩個FF配置文件下測試了它。他們都給我404錯誤。當點擊我的第一個FF配置文件下的鏈接時,我得到了404並沒有任何反應,即我甚至沒有看到向Werkzeug服務器的POST請求,只有GET請求。

在第二FF配置文件我仍然可以在Firebug的控制檯錯誤:

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

所以POST請求被髮送,我看到它在我WERKZEUG日誌:

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 - 

儘管如此,我仍然不要在我的AJAX`.success'調用中完成其他事情(比如將東西存儲到localStorage等)

這是我的jQuery腳本:

<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> 

這是我的看法功能:

@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, 
    }) 

我使用jQuery 2.0.3,瓶0.10.1,瓶,WTF 0.9.4和Firefox 47.0。 我很新的JavaScript和跨瀏覽器的東西有關的JS,所以任何幫助表示讚賞。

P.S.我知道this topic,但在ajax調用中使用'application/json'的accepts沒有幫助。

UPDATE:使用中的鉻和Firefox中的Firebug DevTools,我複製從兩個瀏覽器的捲曲的命令POST請求,並比較其結果:

  1. 鉻(見gist)正常工作,服務器獲取一個請求併發送響應。

  2. Firefox(請參閱gist)不起作用。已發送請求,但永遠不會收到回覆。 cURL' is hanging untill I terminate it with^C'。一旦終止我看到日誌該Werkzeug web服務器返回錯誤400:

    127.0.0.1 - - [09 /月/ 2016 14時29分01秒] 「POST/CTRL /刪除類別HTTP/1.1」 400

+0

嘗試[RESTClient實現(https://addons.mozilla.org/en-US/firefox/addon/restclient/)附加組件Firefox和見你回來了什麼。你可能必須自己寫json。例如:'{'id':'5','csrf':'1'}'。如果沒有顯示任何內容,請嘗試[Fiddler](http://www.telerik.com/fiddler)比較Chrome和Firefox之間請求/響應的不同之處。 – Miro

+0

@Miro謝謝你。我更喜歡使用'httpie'和'cURL'等控制檯工具,並且懷疑它們具有「RESTClient」相同的功能。儘管如此,我無法使用'Fiddler',就像Windows一樣。 其實我調查了FF和Chromium的兩個請求,並更新了我的答案。我仍然不知道什麼是錯的 – vrs

回答

0

好的,我發現了這個問題。

看完這個bug report後,我升級到了jQuery 2.1.1。這導致得到錯誤代碼0而不是404.狀態碼0可能意味着我的腳本在獲得AJAX響應(see this SO topic)之前重新加載頁面。

所以我添加setTimeout 1秒的延遲重新加載頁面之前:

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

這奏效了。

P.S. setTimeout是一個臨時解決方法,以查看它是否解決了問題。做這樣的事情的正確方法是使用承諾see jQuery.when/done