23

In a ajax-driven site I have added some default data using the ajaxSetup, ala this:

var revision = '159';
$.ajaxSetup({
    dataType: "text json",
    contentType: "application/x-www-form-urlencoded; charset=UTF-8",
    data: {
        r: revision
    }
});

This is to ensure cache-miss when a new revision is deployed and the frontend ask for html templates or json-data from the backend. The backend and frontend share the same revision number for this reason.

The problem is that the backend it somewhat unhappy about getting the parameter 'r' when the frontend does a PUT, POST or DELETE. Is there no way to tell jQuery's ajax that this data should only be used when doing GET requests and not when doing POST, PUT or DELETE requests.

UPDATE:

I tried the beforeSend function first, since I knew it. However changing settings.data was possible, but any change seemed to vanish when beforeSend returned. It may have been my fault... :-)

I have settled on the ajaxPreFilter instead. It was not easy as pie though. The options.data is not an object, but the result of $.param(object), so the first challenge was to un-parameterize it. I ended up with this:

var revision = '159';
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
    // do not send data for POST/PUT/DELETE
    if (originalOptions.type !== 'GET' || options.type !== 'GET') {
        return;
    }

    var data = originalOptions.data;
    if (originalOptions.data !== undefined) {
        if (Object.prototype.toString.call(originalOptions.data) === '[object String]') {
            data = $.deparam(originalOptions.data); // see http://benalman.com/code/projects/jquery-bbq/examples/deparam/
        }
    } else {
        data = {};
    }

    options.data = $.param($.extend(data, { r: revision }));
});
Sumurai8
  • 20,333
  • 11
  • 66
  • 100
CodeReaper
  • 5,988
  • 3
  • 35
  • 56

2 Answers2

36

Starting jQuery 1.5, you can handle this much more elegantly via Prefilters:

var revision = '159';
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
    // do not send data for POST/PUT/DELETE
    if(originalOptions.type !== 'GET' || options.type !== 'GET') {
        return;
    }

    options.data = $.extend(originalOptions.data, { r: revision });
});
andrewtweber
  • 24,520
  • 22
  • 88
  • 110
Mrchief
  • 75,126
  • 20
  • 142
  • 189
  • 9
    I'm with jQuery 1.6.4, I can only make it work like this: options.data = $.param($.extend(originalOptions.data, { r: revision })); – Morgan Cheng Mar 27 '12 at 06:55
  • 1
    @MorganCheng: Check if you're setting the right `contentType` and `processData` flag. jQeury would do the serialization accordingly. If your data is an array, you might want to check out `traditional` setting. – Mrchief Mar 27 '12 at 15:56
  • You have a trailing comma on your last line. – steve_c Sep 12 '13 at 17:45
  • jQuery 2.x seems `originalOptions.type` and `options.type` are lower cases, such as `options.type === 'post'` – WeizhongTu Nov 18 '16 at 08:29
  • @WeizhongTu That'd be a violation of the spec: https://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html – Mrchief Nov 18 '16 at 17:23
11

I think what you might be able to use is beforeSend.

var revision = '159';
$.ajaxSetup({
    dataType: "json",
    contentType: "application/x-www-form-urlencoded; charset=UTF-8",
    beforeSend: function(jqXHR, settings) {
        if(settings.type == "GET")
            settings.data = $.extend(settings.data, { ... });
        return true;
    }
});

jqXHR documentation

BeforeSend documentation as well as your settings available

I coded this blind, so I hope it gets you going in the right direction.

Adam Terlson
  • 12,610
  • 4
  • 42
  • 63
  • 2
    What is the difference between $.ajaxPrefilter and beforeSend? – svlada Apr 29 '15 at 12:23
  • @svlada `$.ajaxSetup()` - Set default values for future Ajax requests. `$.ajaxPrefilter()` - Modify existing options before each request is sent. http://stackoverflow.com/a/29843893/2714931 – WeizhongTu Nov 18 '16 at 08:31