通过AJAX的POST请求仅在Firefox中导致错误404

时间:2022-10-07 16:12:54

In my Flask-app I try to implement POST request through AJAX call when user clicks on the link. It works like a charm in Chromium. I have no problems when requesting my view function through httpie either:

在我的Flask-app中,当用户点击链接时,我尝试通过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"
}

But in Firefox something strange happens. I tested it under two FF profiles. Both of them give me 404 error. When clicking the link under my first FF profile I get 404 and nothing happens, i.e. I don't even see POST request to Werkzeug server, only GET request.

但在Firefox中出现了一些奇怪的事情我在两个FF配置文件下测试了它。他们俩都给我404错误。当我点击我的第一个FF配置文件下的链接时,我得到404并且没有任何反应,即我甚至没有看到对Werkzeug服务器的POST请求,只有GET请求。

Under the second FF profile I still get an error in Firebug console:

在第二个FF配置文件下,我仍然在Firebug控制台中出错:

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

So POST request is sent and I see it in my Werkzeug logs:

所以发送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 -

Nonetheless, I still don't get other things done in my AJAX `.success' call (like saving things to localStorage, etc.)

尽管如此,我仍然没有在我的AJAX“.success”调用中完成其他任务(比如将东西保存到localStorage等)

Here is my jQuery script:

这是我的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>

This is my view function:

这是我的视图功能:

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

I'm using jQuery 2.0.3, Flask 0.10.1, Flask-WTF 0.9.4 and Firefox 47.0. I'm very new to javascript and cross-browser things related to js, so any help is appreciated.

我正在使用jQuery 2.0.3,Flask 0.10.1,Flask-WTF 0.9.4和Firefox 47.0。我对js和js相关的跨浏览器的东西很新,所以任何帮助都表示赞赏。

P.S. I'm aware of this topic, but using accepts with 'application/json' in ajax call didn't help.

附:我知道这个话题,但在ajax调用中使用'application / json'接受没有帮助。

UPDATE: Using DevTools in Chromium and Firebug in Firefox, I copied POST requests from both browsers as cURL commands and compared their results:

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

  1. Chromium (see gist) works as expected, server gets a request and sends response.

    Chromium(参见gist)按预期工作,服务器获取请求并发送响应。

  2. Firefox (see gist) doesn't work. Request sent, but response is never received. cURL' is hanging untill I terminate it with^C'. Upon termination I see logs that Werkzeug webserver returns error 400:

    Firefox(参见要点)不起作用。请求已发送,但从未收到响应。 cURL'挂起,直到我用^ C'终止它。终止后,我看到Werkzeug webserver返回错误400的日志:

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

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

1 个解决方案

#1


0  

Okay, I've found the problem.

好的,我发现了问题。

After reading this bug report, I upgraded to jQuery 2.1.1. That resulted in getting error code 0 instead of 404. Status code 0 could mean that my script reloads the page before it gets AJAX response (see this SO topic).

阅读此错误报告后,我升级到jQuery 2.1.1。这导致获得错误代码0而不是404.状态代码0可能意味着我的脚本在获得AJAX响应之前重新加载页面(请参阅此SO主题)。

So I added setTimeout for 1 sec delay before reloading the page:

所以我在重新加载页面之前添加了setTimeout 1秒延迟:

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

And that did the trick.

这就是诀窍。

P.S. setTimeout is a temporary workaround to see if it solves the problem. The right way to do things like that is using promises (see jQuery.when/done)

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

#1


0  

Okay, I've found the problem.

好的,我发现了问题。

After reading this bug report, I upgraded to jQuery 2.1.1. That resulted in getting error code 0 instead of 404. Status code 0 could mean that my script reloads the page before it gets AJAX response (see this SO topic).

阅读此错误报告后,我升级到jQuery 2.1.1。这导致获得错误代码0而不是404.状态代码0可能意味着我的脚本在获得AJAX响应之前重新加载页面(请参阅此SO主题)。

So I added setTimeout for 1 sec delay before reloading the page:

所以我在重新加载页面之前添加了setTimeout 1秒延迟:

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

And that did the trick.

这就是诀窍。

P.S. setTimeout is a temporary workaround to see if it solves the problem. The right way to do things like that is using promises (see jQuery.when/done)

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