jQuery ajax overwrite data/url beforeSend on specific url - javascript

Question
I wanna set a ajax setting for global ajax handled by jQuery
Condition:
If ajax url is 'www.example.com', the data (querystring or body) will append token.
I tried two method
.ajaxPrefilter
$.ajaxPrefilter( function( options, originalOptions, jqXHR ) {
// Add data to ajax option
if (options.url.match(/www\.example\.com/i) !== null) {
originalOptions.data.token = 'i_am_token'
}
});
To add token when url is www.example.com-> it not work!
In console/debugger originalOptions Object is added token property,
but request sent not having token parameter
.ajaxSetup / beforeSend Event
$.ajaxSetup({
beforeSend: function(jqXHR, settings) {
// Only GET Method
if (settings.url.match(/www\.example\.com/i) == null){
settings.url.replace(/((\.\/[a-z][0-9])*\?+[=%&a-z0-9]*)&?token=[a-z0-9]*&?([=%&a-z0-9]*)/gi, "$1$3")
}
},
data: {
token: 'i_am_token'
}
});
And a reverse resolution, add token for each ajax request.
Same as last one, settings.url changed by string replace in the console/debugger.
But request still sent original url.
Test in jsfiddle: http://jsfiddle.net/qVLN2/2/
Thanks for your reading and help :)

You should notice that the String.replace function doesn't affect the original string!
You can try using settings.url = settings.url.replace(....); in your code.

Related

Remove specific request headers set in jQuery.ajaxSetup

I setup some custom headers using
$.ajaxSetup({
headers : {
'x-custom' : 'value'
}
});
It will addx-custom header for all the ajax request. But I want some specific requests to NOT contain this header.
I tried this, delete header from ajaxSettings before that ajax call and add it back when its completed
delete $.ajaxSettings.headers["x-custom"];
$.ajax({
...
"success": function (data) {
$.ajaxSettings.headers["x-custom"] = 'value';
...
}
});
But I feel this is not the correct way, as the request that fired before finishing that call will not get that header. What else can I do please suggest.
Should I add the header back in the next line after $.ajax instead doing it in callback?
Since this question doesn't have any answer that can be marked as Accepted. I am posting the solution.
Looks like adding back the header immediately after the AJAX call would make sense. This way we won't be waiting for success callback and then adding it.
delete $.ajaxSettings.headers["x-custom"]; // Remove header before call
$.ajax({
...
"success": function (data) {
...
}
});
$.ajaxSettings.headers["x-custom"] = 'value'; // Add it back immediately
You could add an ajaxComplete function. It will run after all your ajax requests and do whatever you wish.
Something like this,
$(document).ajaxComplete(function(event, xhr, settings) {
// Add the headers again.
$.ajaxSetup({
headers : {
"x-custom" : "value"
}
});
}
});
You can find the documentation here.
Also, as of jQuery 1.8, the .ajaxComplete() method should only be attached to document.

jQuery AJAX Call Triggers Error Function

I am using this ajax call in my code, but it triggers the error function everytime. Anyone have any idea why this is happening?
$.ajax({
type:'GET',
url: 'https://s3.amazonaws.com/GSTArticles/GoogleMaps/Landmarks.xml',
datatype: 'xml',
success: function(xml){
console.log(xml);
},
error: function(err){
alert("ERROR!");
}
});
To my understanding, the syntax looks correct. Can someone help me to see why this triggers an error, rather than placing the xml into my console? Thanks.
I also see this in the console: XMLHttpRequest cannot load https://s3.amazonaws.com/GSTArticles/GoogleMaps/Landmarks.xml. Origin null is not allowed by Access-Control-Allow-Origin.
You need to use jsonp to do a cross domain request with ajax - which means you can't request XML using jQuery's ajax method. Here are other related questions.
cross domain issue with Jquery
How to Parse XML Cross-domain in jQuery?
You can use Yahoo API library (YQL) to to get the xml though
Source from http://www.cypressnorth.com/blog/programming/cross-domain-ajax-request-with-xml-response-for-iefirefoxchrome-safari-jquery/
// Accepts a url and a callback function to run.
function requestCrossDomain(site, callback) {
// If no url was passed, exit.
if (!site) {
alert('No site was passed.');
return false;
}
// Take the provided url, and add it to a YQL query. Make sure you encode it!
var yql = 'http://query.yahooapis.com/v1/public/yql?q=' + encodeURIComponent('select * from xml where url="' + site + '"') + '&format=xml&callback=?';
// Request that YSQL string, and run a callback function.
// Pass a defined function to prevent cache-busting.
$.getJSON(yql, cbFunc);
function cbFunc(data) {
// If we have something to work with...
if (data.results[0]) {
if (typeof callback === 'function') {
callback(data);
}
}
// Else, Maybe we requested a site that doesn't exist, and nothing returned.
else throw new Error('Nothing returned from getJSON.');
}
}
function xmlSuccess(data){
console.log(data.results[0]);
}
requestCrossDomain('https://s3.amazonaws.com/GSTArticles/GoogleMaps/Landmarks.xml',xmlSuccess);
FIDDLE

How do I resend a failed ajax request?

I have multiple ajax requests some request data every minute others are initiated by the user through a ui.
$.get('/myurl', data).done(function( data ){
// do stuff..
});
The request might fail due to an authentication failure.
I've setup a global .ajaxError() method for catching any failed requests.
$(document).ajaxError(function( e, jqxhr ){
// Correct error..
});
After I catch the error I reset authorization.
Resetting the authorization works but the user has to manually re initiate the ajax call (through the ui).
How do I resend the failed request using the jqxhr originally sent?
(I'm using jQuery for the ajax)
Found this post that suggests a good solution to this problem.
The main thing is to use $.ajaxPrefilter and replace your error handler with a custom one that checks for retries and performs a retry by using the closure's 'originalOptions'.
I'm posting the code just in case it will be offline in the future. Again, the credit belongs to the original author.
// register AJAX prefilter : options, original options
$.ajaxPrefilter(function( options, originalOptions, jqXHR ) {
originalOptions._error = originalOptions.error;
// overwrite error handler for current request
options.error = function( _jqXHR, _textStatus, _errorThrown ){
if (... it should not retry ...){
if( originalOptions._error ) originalOptions._error( _jqXHR, _textStatus, _errorThrown );
return;
};
// else... Call AJAX again with original options
$.ajax( originalOptions);
};
});
In this case, I would write a specific handler for the 403 status code, which means unauthorized (my server would return a 403 too). From the jquery ajax docs, you can do
$.ajax({
statusCode: {
403: function() {
relogin(onSuccess);
}
}
});
to achieve that.
In that handler, I would call a relogin method, passing a function that captures what to do when login succeeds. In this case, you could pass in the method that contains the call you want to run again.
In the code above, relogin should call the login code, and onSuccess should be a function that wraps the code you execute every minute.
EDIT- based on your clarification in comment, that this scenario happens for multiple requests, I personally would create an API for your app that captures the interactions with the server.
app = {};
app.api = {};
// now define all your requests AND request callbacks, that way you can reuse them
app.api.makeRequest1 = function(..){..} // make request 1
app.api._request1Success = function(...){...}// success handler for request 1
app.api._request1Fail = function(...){...}// general fail handler for request 1
/**
A method that will construct a function that is intended to be executed
on auth failure.
#param attempted The method you were trying to execute
#param args The args you want to pass to the method on retry
#return function A function that will retry the attempted method
**/
app.api.generalAuthFail = function(attempted, args){
return function(paramsForFail){ // whatever jquery returns on fail should be the args
if (attempted) attempted(args);
}
}
so with that structure, in your request1 method you would do something like
$().ajax({
....
statusCode: {
403: app.api.generalAuthFail(app.api.request1, someArgs);
}
}}
the generalAuthFailure will return a callback that executes the method you pass in.
The code below will keep the original request and it will try to success 3 times.
var tries = 0;
$( document ).ajaxError(function( event, jqxhr, settings, thrownError ) {
if(tries < 3){
tries++;
$.ajax(this).done(function(){tries=0;});
}
});
You could possibly go by the option of naming each one of your functions and then recalling them as stated in hvgotcodes' answers.
Or
You can use a reusable function to setup a request while extending the defaults:
function getRequest( options ){
var // always get json
defaults = { dataType: 'json' },
settings = $.extend( defaults, options );
return // send initial ajax, if it's all good return the jqxhr object
$.ajax( settings )
// on error
.fail(function( jqxhr, e ){
// if the users autherization has failed out server responds with a 401
if( jqxhr.status === 401 ){
// Authenticate user again
resetAuthentication()
.done(function(){
// resend original ajax also triggering initial callback
$.ajax( settings );
});
}
});
};
To use the above function you would write something like this:
getRequest({
url: 'http://www.example.com/auth.php',
data: {user: 'Mike', pass: '12345'},
success: function(){ // do stuff }
});
The getRequest() could probably be made recursive and/or converted into a jQuery plugin but this was sufficient for my needs.
Note: If the resetAutentication function might faile, getRequest() would have to be recursive.

How to find the ajax status with jQuery 1.2.6

I'm using jQuery 1.2.6 (I know it's old, but I don't have a choice) I need to check the status of my ajax calls. I either want to use:
statusCode, or I could even use error(jqXHR, textStatus, errorThrown), except that textStatus, errorThrown and statusCode, aren't in my jQuery version.
Basically what I have to do, is know if the ajax call was aborted, or had an error for another reason. Any ideas how I can do this?
you could get the status text from the error callback:
$.ajax({
url: "/foo",
dataType: "text",
error: function(obj){
alert(obj.status + "\n" + obj.statusText);
}
});
http://jsfiddle.net/jnXQ4/
you can also get it from the complete callback if the request resulted in an error.
Edit: the ajax request also returns the XMLHttpRequest which you can then bind events to, though I'm not sure how cross-browser it is.
var request = $.ajax(options);
request.onabort = function(){
alert('aborted');
}

jQuery - can I "append" an additional parameter to every get/post request made

I would like to extend jQuery such that every post/get request made on the client side will have an additional parameter sent (always the same key : value). I need this to detect on the client side if the request was made through jQuery, since I have several js libs at work. The additional param is simply jquery : true. A typical request will normally look like this:
jQuery.post('/users/save', { name : 'john', age : 24 }, ....)
Is there a way to append this addition parameter by extending jQuery or some other way such that it'll look like so when it reaches the server:
{ name : 'john', age : 24, jquery : true }
Basically I want to intercept the request and edit it's parameters before they reach the server side. thanks.
Look at beforeSend(XMLHttpRequest)
A pre-callback to modify the
XMLHttpRequest object before it is
sent. Use this to set custom headers
etc. The XMLHttpRequest is passed as
the only argument. This is an Ajax
Event. You may return false in
function to cancel the request
You should be able to use it with ajaxSetup
Try putting the following somewhere in your code before any AJAX request would be executed:
$.ajaxSetup({
beforeSend: function(xhr) {
var newUrl = this.url;
if (newUrl.indexOf("?") != -1) {
newUrl = newUrl + '&jquery=true';
} else {
newUrl = newUrl + '?jquery=true';
}
xhr.open(this.type, newUrl, this.async);
}
});
This will trigger a function before the sending of any AJAX request. The function determines what the new URL should be (based on whether or not any query string has already been attached), then reopens the XMLHttpRequest with the 'jquery=true' attached at the end.
Here's a working demo of this: http://jsfiddle.net/uz9zg/

Categories