首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Ajax GET请求被发送两次

Ajax GET请求被发送两次
EN

Stack Overflow用户
提问于 2019-08-03 01:33:51
回答 5查看 2.3K关注 0票数 11

在作为我的Flask应用程序的一部分运行Ajax请求时,我遇到了令人困惑的行为。我编写了一个处理程序,接收div单击,然后将包含特定数据的Ajax请求发送到app.py中指定的特定路由。然后将数据插入到数据库中。虽然这种方法在我自己的机器上运行我的Flask应用程序时运行得很好,但是当我将我的应用程序移动到另一个托管服务(毕多芬)时,每次单击div,请求都会被发送两次,数据被两次插入数据库就是证明。

以前也问过类似的问题变体(例如这里这里 ),但是这些问题都是处理POST请求的,而我的问题是使用GET。此外,这些问题通常涉及与POST请求一起提交的HTML请求,因此产生了附加请求。但是,我的代码没有任何形式。

我的代码示例(简化,但在本质上与我当前的工作相同):

frontend.html

代码语言:javascript
复制
<div class='wrapper'>
   <div class='submit_stamp' data-timestamp='2019-8-2'>Submit</div>
</div>

frontend.js

代码语言:javascript
复制
$('.wrapper').on('click', '.submit_stamp', function(){
   $.ajax({
     url: "/submit_time",
     type: "get",
     data: {time: $(this).data('timestamp')},
     success: function(response) {
       $('.wrapper').append(response.html);
     },

   });
});

app.py

代码语言:javascript
复制
@app.route('/submit_time')
def submit_time():
   db_manager.submit_stamp(flask.request.args.get('time'))
   return flask.jsonify({'html':'<p>Added timestamp</p>'})

因此,每当我单击submit_stamp元素时,Ajax请求就会触发两次,时间戳会被两次插入到我的数据库中,"Added timestamp"会被两次附加到.wrapper中。为了解决这个问题,我做了一些事情,包括:

  1. 在处理程序中添加event.stopPropagation()
  2. 使用布尔标志系统,在单击后将变量设置为true,并在.ajaxsuccess处理程序中将其重置为false。我在一个条件语句中用这个布尔值包装了$.ajax

这些补丁都不起作用。然而,让我困惑的是,为什么$.ajax在我的机器上运行时只被调用一次,而在主机上运行时却被调用了两次。这和缓存有关吗?我怎样才能解决这个问题?非常感谢!

编辑:

奇怪的是,重复的请求很少发生。有时,只发出一个请求,而另一些时候,请求被重复。但是,我已经在Chrome中检查了Network输出,它只显示单个请求头。

访问日志输出(删除IP):

代码语言:javascript
复制
<IP1> - - [05/Aug/2019:16:35:03 +0000] "GET /submit_time?payload=.... HTTP/1.1" 200 76 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.1) Gecko/2008070208 Firefox/3.0.1" "<IP>" response-time=0.217
<IP2> - - [05/Aug/2019:16:35:05 +0000] "GET /submit_time?payload=.... HTTP/1.1" 200 71 "http://www.katchup.work/create" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36" "<IP2>" response-time=0.198
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2019-08-09 14:10:24

谢谢所有回复的人。最终,我能够用两个不同的解决方案来解决这个问题:

1)首先,我能够通过检查后端的IP来阻止违规请求:

代码语言:javascript
复制
@app.route('/submit_time')
def submit_time():
   _ip = flask.request.environ.get('HTTP_X_REAL_IP', flask.request.remote_addr)
   if _ip == '128.177.108.218':
     return flask.jsonify({'route':'UNDEFINED-RESULT'.lower()})
   return flask.jsonify({"html":'<p>Added timestamp</p>'})

以上实际上更多的是临时攻击,因为无法保证目标IP将保持不变。

2)但是,我发现在HTTPS上运行也删除了重复的请求。最初,我从Pythonanywhere仪表板加载我的应用程序,结果是http://www.testsite.com。但是,一旦我安装了一个正确的SSL证书,刷新了页面,并再次运行了请求,我发现已经产生了所需的结果。

我把奖金颁给了@computercarguy,因为他的帖子促使我考虑了我最初尝试失败的外部/网络相关原因。

票数 3
EN

Stack Overflow用户

发布于 2019-08-05 17:35:56

根据您的最新更新,我不得不说这不是一个重复的请求。您的日志显示,一个请求来自基于Windows的计算机上的Mozilla,而另一个请求来自Mac上的Chrome,这仅仅是来自两个不同位置的两个不同的请求,它们在时间上非常接近。即使它是来自虚拟机的测试,它也不应该记录多个OSs或浏览器,因为VM会处理所有的翻译,防止出现这样的混乱。

您不包括IP地址,但是如果它们是公共地址(如127.x.x.x、10.x.x.x或192.x.x.x以外的其他地址),那么它们肯定是两个同时使用您的软件的不同用户。

如果您跟踪的是相同的用户,可能只是他们使用您的软件在两个不同的设备(如桌面和移动电话)。如果这是不允许的,那么确保他们的访问反映了这一点。如果它可以通过DNS跟踪到不同的地理位置,您可能会有一个受损的帐户锁定,直到真正的用户能够确认他们的身份。

不管你如何分割它,用新的数据,我不认为它实际上是你的软件,除非你可以通过测试甚至可靠地再现它。花点时间考虑一下,它可能不是一个bug,而是一些其他的东西。软件开发人员习惯于认为每件事都是错误和错误,而这可能是一种善意的或恶意的攻击,而这可能是以前没有考虑过的。

祝你好运,希望我能给你一些考虑的东西!

票数 4
EN

Stack Overflow用户

发布于 2019-08-07 03:39:23

非常不寻常的解决方案,但它应该有效(如果不是,我认为这个问题不能用js解决)。

编辑的:检查ajax请求中发送的ID!(所以请检查服务器端!)这肯定是一个独特的标识,所以,您可以用这个@computercarguy car家伙是否正确进行测试。

代码语言:javascript
复制
let ids = []

function generateId(elem) {
    let r = Math.random().toString(36).substring(7)

    while ($.inArray(r, ids) !== -1) {
        r = Math.random().toString(36).substring(7)
    }

    ids.push(r)
    elem.attr("id", r)
}

$(document).ready(function() {
    $(".wrapper").find(".submit_stamp").each(function() {
        generateId($(this))
    })

    console.log(ids)
});

function ajaxHandler(stampElem, usedId) {    
    let testData = new FormData()
    testData.append("time", stampElem.data('timestamp'))
    testData.append("ID", usedId)

    $.ajax({
        url: "/submit_time",
        type: "get",
        data: testData,
        success: function(response) {
            $('.wrapper').append(response.html);
            generateId(stampElem);

            if (stampElem.attr("id").length) {
                console.log("new id:"+stampElem.attr("id"));
            }
        },
    });

}

$(".wrapper").on("click", ".submit_stamp", function(ev) {
    ev.preventDefault()
    ev.stopImmediatePropagation()

    if ($(this).attr("id").length) {
        let id = $(this).attr("id")

        $("#"+id).one("click", $.proxy(ajaxHandler, null, $(this), id))

        $(this).attr("id", "")
    }
});
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57334868

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档