Ajax GET Request is Sent Twice

With your latest update, I'd have to say this isn't a duplicate request. With your log saying one request was from Mozilla on a Windows based machine, and the other request coming from Chrome on a Mac, it's simply 2 different requests coming from two different locations that happen to be close to each other in time. Even if it was a test from a virtual machine, it shouldn't record the multiple OSs or browsers, as VM will take care of all translations, preventing confusion like this.

You don't include IP addresses, but if they are public addresses (as in something other than 127.x.x.x, 10.x.x.x, or 192.x.x.x) then they are definitely two different users that happen to be using your software at the same time.

If you are tracking that it's the same user, it might simply be them using your software on 2 different devices (such as a desktop vs mobile phone). If that's not allowed, then make sure their access reflects this. If it can be tracked through DNS to different geographical locations, you might have a compromised account to lock down until the real user can confirm their identity.

However you slice it, with the new data, I don't think it's actually your software, unless you can reproduce it through testing even somewhat reliably. Take time to consider that it might just Not be a bug, but something else. Software devs are conditioned to think everything is a bug and their fault, when it could be something benign or a malicious attack that might not have been previously considered.

Good luck and hopefully I gave you something to think about!


Thank you to everyone who responded. Ultimately, I was able to resolve this issue with two different solutions:

1) First, I was able to block the offending request by checking the IP in the backend:

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

The above is really more of a temporary hack, as there is no guarantee the target IP will stay the same.

2) However, I discovered that running on HTTPS also removed the duplicate request. Originally, I was loading my app from the Pythonanywhere dashboard, resulting in http://www.testsite.com. However, once I installed a proper SSL certificate, refreshed the page, and ran the request again, I found that the desired result was produced.

I am awarding the bounty to @computercarguy as his post prompted me to think about the external/network related reasons why my original attempt was failing.


Very unusual solution, but it should work (If not, I think the problem can't be solved with js.)

EDITED: Check the sent ID in the ajax request! (So check on server side!) This is sure will be a unique id, so, you can test with this @computercarguy has right or not.

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", "")
    }
});