0

I'm trying to wrap up an ajax request into a library. Im doing this so I do not need to set the headers each time I make a request. The library is loaded asynchronously and has an init method to set the api key. The code seems to work, but I'm getting 2 requests each time I fire off an api call. The library is quite basic and far from finished.

The api that the requests are being made to are coming from a node & express based api. When the same request is made in a rest client they all return the correct data & http status codes.

Here is the code to load my library:

(function(d) {
    var api_key='MY-API-KEY';
    var js,id='tracking-api',ref=d.getElementsByTagName('script')[0];
    if(d.getElementById(id)){return;}
    js=d.createElement('script');js.id=id;js.async=true;
    js.src="/test/track.api.min.js";
    js.onload=function(){stats.init({api_key:api_key})}
    ref.parentNode.insertBefore(js, ref);
})(document);

The un-minified library:

(function(window){

'use strict';

/** 
 *  This library requires jquery to run
 */

var stats= {

    url : 'http://localhost/stats_api/',
    api_key: undefined,

    // The init method will take an api key and set it for our headers
    // used with all api requests
    init: function(opts) {
        if(opts.api_key === undefined) {
            stats.logMsg('Sorry you need to supply an api key');
            return false;
        }
        stats.api_key = opts.api_key;
    },

    // Main api call method nice and simple use - we just give it the
    // method we require and we will be given a json response
    api: function(method, callback) {
        jQuery.ajax({
            url: stats.url + method,
            dataType: 'JSON',
            type: 'GET',
            beforeSend: function(xhr) {
                xhr.setRequestHeader('api_key', stats.api_key);
            },
            success: function(response) {
                callback(response);
            },
            error: function(jqXHR, textStatus, errorThrown) {
                btStats.logMsg(jqXHR);
                btStats.logMsg('Error:' + textStatus);
            }
        });
    },

    // Wrap up the console log function so we can still use it but
    // not break IE8
    logMsg: function(message) {
        if(window.console && console.log) {
            console.log(message);
        }
    }

};

// Attatch our plugin to the window
if(!window.stats){window.stats=stats};

})(window);

The code im using to then make an api request is like so:

stats.api('/visits', function(response){
    console.log(response);
});

The response is always returned correctly, but the majority of the requests 404. When they 404 it also seems to run the query for a second time.

So I guess the questions are, Why is the request being made twice? and Why is jQuery returning a 404 when the request is successful.

Jon Watkins
  • 205
  • 2
  • 11
  • Which browser, are you press CLT+F5? – Vijay Verma Mar 15 '13 at 13:35
  • see here http://stackoverflow.com/questions/5544422/jquery-ajax-executed-twice – PSR Mar 15 '13 at 13:36
  • Im using chrome version 25 on mac osx and the requests are the same regardless how I load the page – Jon Watkins Mar 15 '13 at 13:37
  • Thanks for the link PSR, The headers don't include a 301 redirect its a 404, and unlike the link you posted my requests are not modified, its running both requests twice, but only on a 404. Also there is no Apache server involved its just a simple node.js app. – Jon Watkins Mar 15 '13 at 13:43
  • The minified code is inserting a script tag into the DOM and running an init method once it loads the script, and the library is attaching itself to the window object – Jon Watkins Mar 15 '13 at 13:46
  • @AaronBlenkush Seriously? They're 2, unrelated scripts. The first "minified" script loads the second unminified script. They happen to have different needs, and doesn't matter what's passed - it's how it's used. And they're used correctly in each script – Ian Mar 15 '13 at 13:46

1 Answers1

1

Okay so it turns out this is a really simple issue, as my code is running cross domain jQuery is sending a preflight request with a method of OPTIONS (Didn't notice this earlier) the 404 is coming from my node api as the method was not supported for testing I have added some middleware into the api

app.use(function(req, res, next){

    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header("Access-Control-Allow-Headers", "api_key");

    if(req.method == 'OPTIONS') {
        res.send(200);
    }
    else {
        next();
    }

});

Not ideal as this will allow cross domain scripts for all routes, so I'm going to have to lock this down a little later.

Jon Watkins
  • 205
  • 2
  • 11