【问题标题】:POST request through AJAX results in error 404 in Firefox only通过 AJAX 的 POST 请求仅在 Firefox 中导致错误 404
【发布时间】:2016-07-11 16:49:56
【问题描述】:

在我的 Flask 应用程序中,当用户单击链接时,我尝试通过 AJAX 调用实现 POST 请求。 它就像 Chromium 中的魅力一样。通过httpie 请求查看功能时我也没有问题:

$ 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、Flask 0.10.1、Flask-WTF 0.9.4 和 Firefox 47.0。 我对 javascript 和与 js 相关的跨浏览器的东西非常陌生,因此非常感谢任何帮助。

附:我知道 this topic,但在 ajax 调用中使用 accepts 和 'application/json' 并没有帮助。

更新:使用 Chromium 中的 DevTools 和 Firefox 中的 Firebug,我将来自两个浏览器的 POST 请求复制为 cURL 命令并比较了它们的结果:

  1. Chromium(参见gist)按预期工作,服务器收到请求并发送响应。

  2. Firefox(请参阅gist)不起作用。请求已发送,但从未收到响应。 cURL' is hanging untill I terminate it with^C'。终止后,我看到 Werkzeug 网络服务器返回错误 400 的日志:

    127.0.0.1 - - [09/Jul/2016 14:29:01] "POST /ctrl/remove-category HTTP/1.1" 400

【问题讨论】:

  • 试试 Firefox 的 RESTClient 插件,看看你会得到什么。您可能必须自己编写 json。例如:{'id':'5', 'csrf':'1'}。如果这没有显示任何内容,请尝试 Fiddler 比较 Chrome 和 Firefox 之间请求/响应的不同之处。
  • @Miro 谢谢。我更喜欢httpiecURL 等控制台工具,并怀疑它们具有RESTClient 的相同功能。我不能使用Fiddler,因为它适用于 Windows。实际上,我调查了 FF 和 Chromium 的两个请求并更新了我的答案。我仍然不知道出了什么问题

标签: javascript jquery ajax firefox flask


【解决方案1】:

好的,我找到了问题。

看完这个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); 

这样就成功了。

附: setTimeout 是一个临时解决方法,看看它是否能解决问题。这样做的正确方法是使用 promises (see jQuery.when/done)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-22
    • 2012-04-17
    • 1970-01-01
    • 1970-01-01
    • 2016-05-18
    • 2013-08-27
    • 1970-01-01
    • 2018-09-26
    相关资源
    最近更新 更多