Javascript HTTP request authentication error - javascript

I am trying to call a webservice but I get a authentication error. It is a cross origin request. I have set the 'withcredentials' attribute to manage cross origin requests. But i am still getting the same error.
SOAPClient._loadWsdl = function(url, method, parameters, async, callback)
{
var wsdl = SOAPClient_cacheWsdl[url];
if (wsdl + "" != "" && wsdl + "" != "undefined")
return SOAPClient._sendSoapRequest(url, method, parameters, async, callback, wsdl);
var xmlHttp = SOAPClient._getXmlHttp();
if (SOAPClient.username && SOAPClient.password) {
xmlHttp.open("GET", url + "?wsdl", async, SOAPClient.username, SOAPClient.password);
var auth = "Basic " + SOAPClient._toBase64(SOAPClient.username + ":" + SOAPClient.password);
xmlHttp.withCredentials = true;
//xmlHttp.setRequestHeader( 'Access-Control-Allow-Origin', 'www.website.com');
xmlHttp.setRequestHeader('Authorization', auth);
} else {
xmlHttp.open("GET", url + "?wsdl", async);
}
if (async) {
xmlHttp.onreadystatechange = function() {
alert(xmlHttp.readyState);
if (xmlHttp.readyState == 4)
SOAPClient._onLoadWsdl(url, method, parameters, async, callback, xmlHttp);
}
}
xmlHttp.send(null);
if (!async) `enter code here`
return SOAPClient._onLoadWsdl(url, method, parameters, async, callback, xmlHttp);
}

I suspect this is due to limitations of the browser that won't allow you to do a CORS request. The header would have to be set on the remote server to permit this and it sounds like you don't control it.
Create a server proxy at the domain of the page that can fetch the desired result from the other domain and relay it to you from the allowed domain.
You may want to post the URL of the WDSL server to see if other people can consume it.
p.s.
&& wsdl + "" != "undefined")
This will never evaluate to undefined because you are always concatenating an empty string.

Related

Setting a custom content-type xmlhttprequest

I have an API I am trying to interface with that requires a custom content-type header be set, with the value text/xmlmc
I've implemented this like so
Xmlmc.prototype.submitRequest = function (request,callback) {
var self = this;
var port = portMap[request.service] || 5015;
var endpoint = this.endpoint = 'http://' + this.server + ':' + port;
var xml = request.toXml();
var xhttp;
if (window.XMLHttpRequest) {
xhttp = new XMLHttpRequest();
} else {
// IE 5 and 6 makes us sad. Please don't use it
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
//handle request
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4) {
var response = self.handleResponse(xhttp);
callback(response);
}
};
xhttp.open('POST',endpoint,true);
xhttp.setRequestHeader('Content-type', 'text/xmlmc');
//xhttp.setRequestHeader('Content-length', xml.length.toString());
if(this.sessionCookie != '') {
xhttp.setRequestHeader('Cookie', this.sessionCookie);
}
xhttp.send(xml);
};
The endpoint is localhost:5015
When I do this, the request fails and never even sends. When I use a standard request header like 'text/plain' the request is sent but returns a status code of 501 not implemented. How can I set a custom HTTP header in an xmlhttprequest?
It turns out this was due to a cross origin issue. Even when the domain is the same, if the ports are different it is a problem. I fixed the issue by adding a reverse proxy to my apache configuration and now I can query the api without cross origin requests. Unfortunately I don't have access to change the API and allow cross origin domains.

Any way to make AJAX calls to Gmail API without going through JS library?

A simple guide to making a GET request to get a user's messages through Gmail API can be found here.
But the way we are instructed to do the request is in the following manner:
function getMessage(userId, messageId, callback) {
var request = gapi.client.gmail.users.messages.get({
'userId': userId,
'id': messageId
});
request.execute(callback);
}
Is it possible to make the request using the good ol' XMLHttpRequest object on the client side? If so what parameters should be passed into the call?
I have tried this:
var getMessages = function() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200)
console.log(xhr.responseText);
}
xhr.open( "GET", "https://www.googleapis.com/gmail/v1/users/me/messages", true );
xhr.send();
}
But I get a 401, even after authenticating.
As it states in this answer, you should pass the access token as a query parameter with the name access_token, or prefix the authorization header value with "Bearer", like so:
xhr.setRequestHeader("authorization", "Bearer " + userToken.access_token);

Get Date Header Asyncronously

As the title says, I want to get the Response Header Date value, but I keep getting the following warning :
Synchronous XMLHttpRequest on the main thread is deprecated because of
its detrimental effects to the end user's experience. For more help,
check https://xhr.spec.whatwg.org/.
My code :
function getxmlhttp () {
// although IE supports the XMLHttpRequest object, but it does not work on local files.
var forceActiveX = (window.ActiveXObject && location.protocol === "file:");
if (window.XMLHttpRequest && !forceActiveX) {
return new XMLHttpRequest();
}else {
try {
return new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {}
}
alert ("Your browser doesn't support XML handling!");
return null;
};
function srvTime(){
xmlHttp = getxmlhttp();
//xmlHttp.open('HEAD',window.location.href.toString(),false);
//need to send this to a non-volitile page
xmlHttp.open('GET',"blank.php",false);
xmlHttp.setRequestHeader("Content-Type", "text/html");
xmlHttp.send(null);
console.log("raw " + xmlHttp.getResponseHeader("Date"));
return xmlHttp.getResponseHeader("Date");
};
When I switch this line:
xmlHttp.open('GET',"blank.php",true);
To be true, the value returns NULL.
So can this be done, or do I have to just live with the warning in the console?
Thank you
As your title states, you must make the request asynchronously. That means you have to issue the request and wait for it to complete to get the information. Something like this should work:
function srvTime(callback) {
xmlHttp = getxmlhttp();
//xmlHttp.open('HEAD',window.location.href.toString(),false);
//need to send this to a non-volitile page
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState == 4) { // The operation is complete
console.log("raw " + xmlHttp.getResponseHeader("Date"));
callback(xmlHttp.getResponseHeader("Date"));
xmlHttp = null;
}
};
xmlHttp.open('GET', "blank.php", true);
xmlHttp.setRequestHeader("Content-Type", "text/html");
xmlHttp.send(null);
};
Note that you must change the signature of your srvTime method. You can't return the data from it, the caller must supply a callback function that receives the date once the request completes.
An example of how you would use this function with the new signature is as follows:
srvTime(function (serverDate) {
document.getElementById("clock").innerHTML = "Game Time: " + serverDate;
});

Cross domain Ajax requests with Symfony2 (example with FOSUserBundle)

I have a domain A "xbo.dev" and a sub domain B "blog.xbo.dev".
For example, on B domain, I would like to make an Ajax request to a domain A function.
I'm trying this with FOSUserBundle authentication. What I do :
var xhr = new XMLHttpRequest();
if ('withCredentials' in xhr) {
xhr.open('POST', 'http://xbo.dev/ajax/check_login_ajax', true);
// I am using hard coding for the URL because with Routing.generate I would have this URL : http://blog.xbo.dev/ajax/check_login_ajax
// which is not good because the request is on a different domain
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 400) {
console.log(xhr);
console.log('ok');
} else {
console.log('ko');
}
}
};
xhr.send(encodeURI('_username=' + $('#co_'+varName+'username').val() + '&_password=' + $('#co_'+varName+'password').val() + '&_remember_me=' + false + '&_csrf_token=' + $('#co__csrf_token').val()));
I have a "ok" displayed by my request but nothing special is happening (I should have something like "Bad credentials" or "success" (or others), returned by FOSUserBundle check_login_ajax function, but no one of those is displayed...)
How can I do ?
EDIT 1 : Here is the result I have each time, either the login / password are correct or not
And with a normal $.ajax, I have this :
You need to implement something to relax the same-origin policy such as CORS.
As to your in-code note about hard-coding vs using the router to generate URLs, Symfony's router supports hostnames.

Setting up CORS not working

I have the following headers set on the server
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT");
response.addHeader("Access-Control-Allow-Headers","X-Custom-Header");
And i want to use the POST method to access a web service and send data to it but the problem is my setting up with the server is causing problems
I used the following method
function createCORSRequest(method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
// XHR for Chrome/Safari/Firefox.
xhr.open(method, url, true);
}
else if (typeof XDomainRequest != "undefined") {
// XDomainRequest for IE.
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
// CORS not supported.
xhr = null;
}
return xhr;
}
and based on this object
url = "http://myurl.do";
var xhr = createCORSRequest('POST', url);
if (!xhr) {
alert('CORS not supported');
return;
}
var params = "name=pari123&action=initaction&gameId=slotreel3";
xhr.setRequestHeader('Content-Type', 'application/text/plain');
if(xhr.readyState == 4 && xhr.status == 200)
{
alert('Tested OK')
xhr.send(params);
}
else
{
alert('status not 200 or xhr is not ready');
}
// Response handlers.
xhr.onload = function() {
var text = xhr.responseText;
alert('Response from CORS request to ' + url + ': ' + text);
};
xhr.onerror = function() {
alert('Woops, there was an error making the request.');
};
But always it alerts a message saying 'status not 200 or xhr is not ready' i am not able to proceed any one if you know please kindly help!
when i print the xhr.readyState its printing a value of 1
if(xhr.readyState == 4 && xhr.status == 200)
This check must be placed in the onreadystatechange event handler. You obviously cannot have a 200 status code or a "finished" request before actually sending it.
What you wanted is probably this:
xhr.onreadystatechange = function() {
if(xhr.readyState == 4 && xhr.status == 200) {
alert('Tested OK');
var text = xhr.responseText;
alert('Response from CORS request to ' + url + ': ' + text);
}
};
xhr.send(params);
If you want an else case to check for errors remember that you still need to check for xhr.readyState == 4. You don't want your error-handling code to run for other readyStates.
There is no need for the onload event - when you get readyState == 4 you know the request has finished.
There can be several issues here.
I observed that different browsers implement CORS differently. My experience is based on Firefox and Google Chrome. For example, I had to add a special header on server side, so that Firefox would make the preflight (OPTIONS) request and the actual request (GET,PUT etc.) using one connection as Google Chrome does it. You would have to add on the server side:
response.addHeader("Keep-Alive", "timeout=2, max=100");
response.addHeader("Connection", "Keep-Alive");
I also noticed that some browsers do not like the wildcard ("*") in the CORS headers. A workaround for the line
response.addHeader("Access-Control-Allow-Origin", "*");
would be to return the origin of the request and not a wildcard.
However, there could be also other problems and we would need more details. For example, does the request work when the server is hosted on the same domain (i.e. the problem might not be related to CORS). What server are you using?
xhr.send(); needs to be just after the call to xhr.open(); does it not? Status 1 means the request has not been sent yet, it'll never get to status 4 unless you actually send the request..

Categories