Android Phonegap: $.ajax does not fire callback for unauthorized (401) - android

I'm using PhoneGap to build an Android app. Using either jQuery or Zepto, I'm able to make calls to the website APIs using the $.ajax call. However, when the website returns a 401 (unauthorized) response, there seems to be no callback from the ajax call - none of "success", "error", or "complete" get called.
Note that the same code works fine when the response is 200 or 500.
I'm using Zepto 1.0rc1 and/or jQuery 1.7.2 with PhoneGap 1.6.1 .
function make_base_auth(user, password) {
var tok = user + ':' + password;
var hash = btoa(tok);
return "Basic " + hash;
}
$('#button').on('touchstart', function() {
console.log("UPLOAD --- ");
$.ajax({
url: 'https://mywebsite/api/v1.0/test/?ts=' + new Date().getTime(),
type: 'GET',
beforeSend: function (xhr){
xhr.setRequestHeader('Authorization', make_base_auth('username', 'password'));
},
success: function(data, status, xhr) {
console.log("AJAX: SUCCESS: " + data);
$('h1').text("AJAX!!");
},
error: function(xhr, errortype, error) {
console.log("AJAX: FAIL: " + errortype + " - " + error);
$('h1').text("AJAX FAIL");
},
complete: function() {
console.log("--- Complete");
}
});
return false;
});

I just had the same problem. When I get HTTP 401 back and use
$.ajax({
...
timeout: 5000, // Some timeout value that makes sense
...
});
then the error callback is called with {"readyState":0,"status":0,"statusText":"timeout"}. In that case you would have to guess that the real error is the HTTP 401.
Alternatively you can use
$.ajax({
...
async: false, // :-(
...
});
and your error callback will get something like {"readyState":4,"responseText":"<html>...</html>","status":401,"statusText":"Unauthorized"} back.

Downgrade phonegap. Yes. You read that right.
I tried 1.4.1: didn't work.
I tried 1.3.0: works.
So yeah, that's that.

Related

Angular 4 : HTTPClient alway return an error 0

Hello i'm in trouble with angular HTTPclient.
I'm using Ionic 3 and Cordova so i cant use JQuery, that's why i use HTTPClient.
I have the following lines in my code :
var body = new URLSearchParams();
body.set('base64', this.getBase64Image(this.image));
body.set('x_poisson', "" + 0);
body.set('y_poisson', "" + 0);
body.set('x_gabarit', "" + this.points[this.points.length - 2]);
body.set('y_gabarit', "" + this.points[this.points.length - 1]);
body.set('largeur_image', "" + this.image.width);
body.set('hauteur_image', "" + this.image.height);
body.set('pseudo', pseudo);
var url = UrlServeur + "/index.php?module=Homologation&action=traiterPhotoApplication&listeCoin=" + corners;
console.log("[LOG][HOMO] Requesting on url: " + url);
this.http.post(url, body).subscribe(response => {
console.log("[LOG][HOMO] Homologation response: " + response);
loading.dismiss();
}, err => {
console.log(`[ERR][HOMO] Homologation error: (${err.status}) ${err.error}`);
loading.dismiss();
});
The probleme is that HTTPClient considere all response as error and i'm unable to get the body when i'm supposed to recieve a JSON.
Here are the log i have :
[17:09:59] console.log: [LOG][HOMO] Requesting on url:
http://X.XXX.XX.XXX/cdp/index.php?module=Homologation&action=traiterPhotoApplication&listeCoin=XXX,XXX,XXX,XXX,XXXX,XXX,XXXX,XXXX
[17:10:28] console.log: [ERR][HOMO] Homologation error: (0) undefined
When i watch on the logs of the serve X.XXX.XX.XXX it look like everything went well.
Thanks for reading, don't hesitate to ask for more informations.
Edit 1:
When i don't use an URLSearchParam the server don't get the post data event when manually setting post type to application/json manually
I tried with ResponseContentType as text :
var options = new RequestOptions();
options.responseType = ResponseContentType.Text;
this.http.post(url, body, options).subscribe(response => {
console.log(`[LOG][HOMO] Homologation response: ${response}`);
loading.dismiss();
}, err => {
console.log(`[ERR][HOMO] Homologation error: (${err.status}) [${err.error}] ${err}`);
loading.dismiss();
});
An i still get the following log : [ERR][HOMO] Homologation error: (0) [undefined] Response with status: 0 for URL: null
Edit 2:
It work when i build the app using ionic cordova build android --prod but not if i test using ionic cordova run android -lc
try send to post a simple obj (not a URLSearchParams)
var body:any = {
'base64':this.getBase64Image(this.image),
'x_poisson': "" + 0,
'y_poisson': "" + 0,
'x_gabarit': "" + this.points[this.points.length - 2],
'y_gabarit': "" + this.points[this.points.length - 1],
'largeur_image': "" + this.image.width,
'hauteur_image': "" + this.image.height,
'pseudo': pseudo
}
You also can try see if the response is "text" and not a json Object
this.http.post(url, body,{ responseType: 'text' })

Worklight authentication error 401 after successfully IMC authentication

I used this code to pass the IMC server and authenticate my WL 6.2 server ( WL server does not require any authentication ).
PADMAppRealmChallengeHandler.loginToImc = function (userid, password) {
PADMAppRealmChallengeHandler.writeMessage("Authenticating with w3 IMC server ...");
PADMAppRealmChallengeHandler.writeMessage("Called loginToImc ...");
if (byPassIMC)
{
}
else
{
base64uid = window.btoa(userid + ":" + password);
// var WgSessionKey = WLJQ.cookie("WgSessionKey");
alert("Cookies are: " + document.cookie );
// alert("WgSessionKey=" + WgSessionKey);
WLJQ.ajax({
url: IMCURL,
method: "get",
async: false,
cache : false,
crossDomain : true ,
headers : {
"Authorization": "Basic " + base64uid
//, "Cookie" : "WgSessionKey=XXXXX"
},
dataType: "text",
error: function(jqXHR, status, error) {
console.log("status =" + status + " error=" + error);
console.log(jqXHR);
console.log("AllResponseHeaders");
console.log("================================");
console.log( jqXHR.getAllResponseHeaders() );
PADMAppRealmChallengeHandler.writeError("Failed to authenticate. Please try again later");
console.log("============== error responseText ==================");
console.log( jqXHR.responseText);
console.log("================================");
PADMAppRealmChallengeHandler.setBusy(false);
},
timeout: 12000,
success : function(data, textStatus, jqXHR) {
console.log("================================");
PADMAppRealmChallengeHandler.writeMessage("IMC SUCC ");
console.log("================================");
console.log(jqXHR);
console.log("AllResponseHeaders");
console.log("================================");
console.log( jqXHR.getAllResponseHeaders() );
console.log(data);
console.log("================================");
var SetCookies = jqXHR.getResponseHeader('Set-Cookie');
// alert("SetCookies=" + SetCookies );
console.log("============== success responseText ==================");
console.log( jqXHR.responseText);
console.log("================================");
// if (data == "Success!!")
if (data)
{
var options =
{
onSuccess: function(e)
{
PADMAppRealmChallengeHandler.writeMessage("Workligth Connect + IMC SUCC ");
PADMAppRealmChallengeHandler.writeMessage(JSON.stringify(e));
PADMAppRealmChallengeHandler.setBusy(false);
return;
},
onFailure: function(e)
{
PADMAppRealmChallengeHandler.writeError("Failed to authenticate with Worklight. Please try again later");
PADMAppRealmChallengeHandler.setBusy(false);
alert("Error with Workligth server " + JSON.stringify(e));
}
};
console.log("Run WL.Client.connect(options); ");
WL.Client.connect(options);
} else {
PADMAppRealmChallengeHandler.writeError("The user ID or password entered is incorrect");
alert("Failed to login on IMC server, verify your user and/or password please !!");
PADMAppRealmChallengeHandler.setBusy(false);
}
}
});
}
};
after the a good ajax get request, the WL.client.connect() request is reject by IMC , error 401 .. unauthenticate.
The issue happens on
WL Studio | Android | iOS
v6.3 | Error 401 | not tested
v6.2 | Error 410 | WORKS !
v6.1 | WOKRS | not tested
v5.X | WORKS | not tested
It seems the issue is due the fact the Set-Cookie WgSessionKey is not capture by the WL framework. It happens only on Android. It seems a bug introduced on WL 6.2 on Android
In Worklight 6.2 there is no publically supported way of accessing the Android cookie store. This is a known limitation of the platform.
An alternative, undocumented, unsupported, method was provided to the user in order to over the problem:
var req=new WLJSX.Ajax.WLRequest( ... instead of WLJQ.ajax({ ...
The plan is to add proper Android cookie store support via public API in a future release. It will then be possible to inject anything needed...

Android browser times out Ajax request

I am submitting a form via ajax (using JQuery) and the time taken for the response to be received can be anything from a few seconds to a few minutes. This is expected and cannot be changed. This is working fine in all browsers except the stock Android browser which is timing out my request after 120 seconds, no matter what I set the timeout to in the ajax constructor. Is there a way around this?
The code for the Ajax request is quite simple:
var jqxhr = $.ajax({
type: 'post',
timeout: 500000,
url: 'process.php',
data: $('form').serialize(),
success: function (data) {
alert("success" + data);
},
error: function(xhr, error){
alert("Error: " + error + ", XHR status: " + xhr.status);
},
});
When submitted on Android with a script that takes over 120 seconds, the error handler is hit with the following message:
Error: error, XHR status: 0
Please have a look at this article indicating that the error may arise from the presence of a HTTP Expires header.
Use a tool like Fiddler to monitor the HTTP network traffic and present the results for further analysis.
You have a syntax error.
var jqxhr = $.ajax({
type: 'post',
timeout: 500000,
url: 'process.php',
data: $('form').serialize(),
success: function (data) {
alert("success" + data"); <------- HERE
},
error: function(xhr, error){
alert("Error: " + error + ", XHR status: " + xhr.status);
},
});
Try your code with this on-line JavaScript runner but remove the extra double qoute.
var jqxhr = $.ajax({
type: 'post',
timeout: 500000,
url: 'process.php',
data: $('form').serialize(),
success: function (data) {
alert("success" + data);
},
error: function(xhr, error){
alert("Error: " + error + ", XHR status: " + xhr.status);
},
});
After some research it appears that others have had similar issues with AJAX timeouts at ~60ms and ~120ms. Those seem like very deliberate values (like internal browser settings), and I am going to go ahead and assume from the lack of responses/solutions that we can't get around those timeouts.
Have you considered posting your AJAX request to a separate server/service which does not do any processing and can return a quick 200 OK response. Then let this second server handle the communication with the slow server. I know this sucks, but it might be your only solution (and might result in a snappier app and happier users).
Can you give any more insight into your app? Is this a PhoneGap app or is the app hosted at some domain that you can access from the browser? Are you able to provide a URL?
Have you seen the below thread.
AJAX (XmlHttpRequest) timeout length by browser
Regards,
SP
Try inserting your code on a separate blank html page with nothing but your ajax request, jquery attached and some basic alerts like success, status code or errors etc. Put the correct file path in url handler, in data handler, put some static values like name:"Macros",site:"stackoverflow". When all gets ready, you should get alert message on desktop browser, if its success, try running that html page on stock android browser. If that works as well.. The problem might be jquery conflict with some other script or your $("form#testform").serialize() function.
How about if you retry after the timeout?
$("form#testform").submit(function(){
var allFormValues = $("form#testform").serialize();
$.ajax({
cache:false,
timeout:8000, // I chose 8 secs for kicks
tryCount : 0,
retryLimit : 5,
type:"POST",
url:"someurl.php",
data:allFormValues,
error:function(xhr, status, error) {
if (status == 'timeout') {
this.tryCount++;
if (this.tryCount <= this.retryLimit) {
alert("Timeout! Retrying now!");
//try again
$.ajax(this);
return;
}
return;
} else {
// not a timeout? not a problem
alert("Error: " + status + ", XHR status: " + xhr.status);
}
},
success:function(response){
alert(response);
}
});
});

Android + JQM+ jsonp not working consistently

I am crunntly working on Hybrid Android App using JQM + PhoneGap
I am doing a JSONP request with AJAX
It works well on all Chrome PC browser, also works well on my android application when WiFi is connected,
but when changing network connection to 3G the AJAX request is not responding.
I found #BruceHill related post that wrote the following :
"mobile operators do content modification before delivering it to the phone and this modification breaks jQuery"
Jquery mobile page not loading correctly on Netherlands 3G connections
Although I am not living in Holland, I tried doing what he suggests by locating all the JS files on a remote server and called it via CDN, but unfortunately it didn't help.
I will be happy to get some help on this one...
this is my AJAX request:
$.mobile.allowCrossDomainPages = true;
$('#expertsListPage').live('pageshow', function (event) {
$.mobile.showPageLoadingMsg();
getExpertsList();
});
var catId;
var catName
function getExpertsList() {
$('#expertsList li').remove();
catId = getUrlVars()["id"];
catName = getUrlVars()["cat"] ;
$('h1').text( unescape(catName) );
var url = 'http://apis.mydomain.com/mydata.svc/jsonp'
$.ajax({
cache: true,
type: 'GET',
url: url,
dataType: 'jsonp' ,
jsonp: 'callback',
success:api_do
});
}
var expertss;
function api_do(obj) {
$('#expertsList li').remove();
expertss = obj.experts;
$.each(expertss, function (index, expert) {
$('#expertsList').append('<li><a href="ExpertDetails.html?id=' + expert.id + '&catid=' + catId +'&catName=' + catName + '">' +
'<img style="width:160px;height:160px;" src="' + expert.thumbnail + '"/>' +
'<h4>' + expert.name + '</h4>' +
'<p>' + expert.description + '</p>' +
'</a></li>');
});
$('#expertsList').listview('refresh');
$.mobile.hidePageLoadingMsg();
}
function getUrlVars() {
var varsExperts = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for (var i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
varsExperts.push(hash[0]);
varsExperts[hash[0]] = hash[1];
}
return varsExperts;
}
Try adding this code to your javascript, might help.
$( document ).on( "mobileinit", function() {
// Make your jQuery Mobile framework configuration changes here!
$.support.cors = true;
$.mobile.allowCrossDomainPages = true;
});

How do I enable Third-Party Cookies under Phonegap and Android 3.2?

I am using $getJSON to hit a node.js endpoint under Phonegap and Android. The code looks like this
$.getJSON(
serverURL + "/login?callback=?",
"playerId=" + playerId + "&pwd=" + pwd,
function(data){
theCallbackFunction.call(null, JSON.parse(data));
},
function(jqXHR, textStatus, errorThrown) {
alert('error ' + textStatus + " " + errorThrown);
}
);
In response to the login request, my server sends back a session cookie. This cookie is only accepted and returned in subsequent AJAX requests if 'Third-Party Cookies' are enabled in the browser. I have found that older Android devices (e.g. 2.2) allow this by default but new ones (3.2) do not.
Is it possible to force Phonegap to enable Third-Party Cookies for my Android application?
I had a similar problem when trying to authenticate with my server. I instead resorted to the use of localStorage. See the code below or here.
var store = window.localStorage,
request = {
url: {SERVER_URL},
headers : {
Cookie: store.getItem('session')
},
complete: function (jqXHR, status){
if (status != 'success') {
console.log('ajax status: failure');
} else if (store.getItem('session') != null) {
console.log('ajax status: session exists');
} else {
console.log('ajax status: saving cookie');
var header = jqXHR.getAllResponseHeaders();
var match = header.match(/(Set-Cookie|set-cookie): (.+?);/);
if (match) {
session = match[2];
store.setItem("session", session);
}
}
}
}
$.ajax(request);
In the above, I'm checking for the localStorage variable 'session' and if it exists, it will send the stored cookie. If it doesn't exist, it will take the 'set-cookie' paramater sent in the headers by the server, match the pertinent part and store it in the 'session' variable of localStorage.
Phonegap does not support cookie abstraction. Never really needed to as there are already apps/plug-ins that do. Plus it is intended to wrap up the functionality of the phone/device, not the browser. You CAN however do this with a jQuery plug-in.
https://github.com/carhartl/jquery-cookie

Categories

Resources