XMLHttpRequest - REST from javascript - javascript

I am having a webserver running on my localhost. If i load my webpage from my webserver everything works fine. I am able to OPEN a REST session with my webserver.
JS code :--
$(document).ready(function() {
var xhr = new XMLHttpRequest();
var open_str = "http://localhost:8080/vscp/rest?user=admin&password=d50c3180375c27927c22e42a379c3f67&format=json&op=1";
xhr.open("GET", open_str, true);
xhr.onreadystatechange = function() {
alert(xhr.readyState + "" + xhr.status);
if (xhr.readyState == 4 && xhr.status == 200) {
alert("session opend success");
var json = JSON.parse(xhr.responseText);
alert(JSON.stringify(json, null, 10));
}
}
xhr.send();
});
HTML code :--
<!DOCTYPE html>
<html>
<head>
<title>Hello jQuery</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="hello.js"></script>
</head>
<body>
<div>
<p class="greeting-id">Trying to open the REST session with vscpd </p>
</div>
</body>
</html>
Now if i load the same html page from my D: drive :--
file:///D:my_folder/htm_test.html
I am getting following error "No 'Access-Control-Allow-Origin' header is present". And i have checked in javascript code that xhr.readyState is 4 and xhr.status is 0.
Please suggest what changes to make to my javascript code so that, if i open the html file directly from my D: drive using file:/// then also REST session is opened correctly with my webserver.
========================= JSONP code ========================
$(document).ready(function() {
var url = "http://localhost:8080/vscp/rest?user=admin&password=d50c3180375c27927c22e42a379c3f67&format=json&op=1";
function jsonpCallback(response) {
alert('success');
}
$.ajax({
url: url,
dataType: 'jsonp',
error: function(xhr, status, error) {
alert("error" + " " + error.message);
},
success: jsonpCallback
});
return false;
});
Error i get :--
server is sending the right response :--
{"success":true,"code":1,"message":"success","description":"Success","session-id":"e5a36e14b687c37b615dbc6a9506df5c","nEvents":0}
But ajax call giving error for this response i.e "Uncaught SyntaxError: Unexpected token :"

You have run into the Same Origin Policy - this is a security mechanism that restricts JavaScript loaded from one domain from sending requests to a different domain.
There are various ways around it, if you are using Google Chrome I would suggest setting the --allow-file-access-from-files flag when you start the browser, Firefox also provides a way to work around it, but don't forget to disable these options when you have finished testing, they are there for a good reason!

That's because Chrome and some other browsers are blocking the local files for security reasons and I don't think there is a method for resolving this issue. You have to use a webserver.

Related

Access-control-allow-origin issue on server side?

I need to send a get request to a company internal website on client side. Here is my code:
<head>
<script src="https://code.jquery.com/jquery-1.12.4.js" integrity="sha256-Qw82+bXyGq6MydymqBxNPYTaUXXq7c8v3CwiYwLLNXU=" crossorigin="anonymous"></script>
<script type='text/javascript'>
$(document).ready(function () {
var url = 'https://jsonplaceholder.typicode.com/photos'; //working
//var url = 'xxxxxxx'; //internal url (returns json), not working
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true)
xhr.onload = function () {
if (xhr.readyState === xhr.DONE) {
console.log(xhr.response)
console.log(xhr.responseText)
}
}
xhr.send()
})
</script>
</head>
This works fine with a test url that I put in (of course, having different domain than my server), meaning that it works fine with CORS request.
However, it doesn't work with the internal company url. The error I got is “No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'abc'(my server) is therefore not allowed access.”
My question: What caused the error? Why my CORS request works with one website but not the other? Is there some restrictions on my company's internal website, e.g. my server is not whitelisted on its "origin firewall"?
Interesting enough, it works (i.e. I'm able to get the json response) if I use ajax and set dataType to jsonp. But of course, because the returned data is json not jsonp, I got a different error saying "unexpected token :". This made me to doubt myself. If it was something placed by the internal website, why does ajax/jsonp trick work?
The ajax code below works - it got valid json response. However, because the returned data is json not jsonp, I got a different error (as I expeted).
$.ajax({
url: 'xxxxxxx', //internal url (returns json)
dataType: 'jsonp',
success: function( response ) {
console.log( response ); // server response
}
});

Checking if a URL exists or not in Client Side Code

My objective is to check whether a URL is valid or not from client side. I tried the following things:
1. Tried using a ajax request using dataType as JSON. - Got the Cross-Origin Request Blocked error.
2. Tried using the JSONP as datatype. - Worked fine for some websites like google.com but it cribed for others like facebook.com
Got the error like "Refused to execute script from
FaceBook
callback=jQuery32107833494968122849_1505110738710&_=1505110738711'
because its MIME type
('text/html') is not executable, and strict MIME type checking is enabled."
Is there any workaround for this. I just want to make sure that the URL is valid irrespective of the content in the response.
Following is the code I wrote:
<html>
<body>
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
</script>
<script>
function CallPageMethod() {
$.ajax({
type: "GET",
url: "https://www.google.com/",
dataType: "jsonp",
success: function (data, textStatus, xhr) {
alert("Success");
},
error: function (data, textStatus, xhr) {
if (data.status === 200) {
alert("Finally I am done")
} else {
alert("Error");
}
},
});
}
</script>
<Button onclick="CallPageMethod()">Test URL</Button>
</body>
</html>
Any Suggestions or any alternative approach that I should follow to resolve this issue?
Not properly, but Most sites have a favicon.ico either from the site directly or provided from the hosting company for the site if it is a 404 image.
<img src="https://www.google.com/favicon.ico"
onload="alert('icon loaded')">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"
onload="alert('ajax loaded')"></script>
Although iframe and object do have onload events, invalid pages also trigger the event.
This would be the fastest site test I can think of ...
var img = new Image();
img.onload = function () {
alert("image width is " + img.naturalWidth + " not zero so site is valid");
}
img.src = "https://www.google.com/favicon.ico";
As for facebook, the each page uses resources from another url, iframes are blocked as well as scripts. You would need to make the request from a server to test if a page existed.
You're best off writing a proxy on your server so:
Client hits your server with the URL you want to check
Your server makes the request to that URL and gets a response (or not)
Server returns status code to the client
This way will avoid the CORS issues you're having to navigate and will allow you to set any HTTP headers you need to.

Why does JavaScript alert display an empty string in Phonegap Android App while the code is working perfectly fine on browser?

I'm working on a simple PhoneGap application that communicates with a server that runs PHP, gets a string and displays it in JavaScript alert.
The App works perfectly fine on a browser. The JavaScript alert displays the string returned by the PHP code on the server. This action happens on click event of a button.
Here is the markup:
<!DOCTYPE html>
<html xml:lang="en" lang="en">
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;">
<title>PhoneGap</title>
<script type="text/javascript" charset="utf-8" src="jquery.min.js"></script>
<script src="cordova.js" charset="utf-8" type="text/javascript"></script>
<script type="text/javascript" charset="utf-8" src="index.js"></script>
</head>
<body>
<h1>Hello World!</h1>
<button id="eventfire">Click</button>
</body>
</html>
JS code
$(document).ready(function(){
$("#eventfire").click(function(){
var data = {
"action": "test"
};
data=$.parseJSON('{ "name": "John" }');
$.ajax({
type: "POST",
dataType: "text",
url: "http://192.168.x.x/HelloWorldTest/response.php", //Relative or absolute path to response.php file
data: data,
success: function(data) {
alert(data);
alert("type is " + typeof data + ". Length is " + data.length);
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.statusText);
alert(xhr.responseText);
alert(xhr.status);
alert(thrownError);
},
statusCode: {
400: function () {
alert("Bad request!");
},
401: function() {
alert("Unauthorized!");
},
403: function() {
alert("Forbidden!");
},
404: function() {
alert("Page not found!");
},
408: function() {
alert("Request Timeout!");
},
200: function() {
alert("page reached");
},
}
});
});
})
PHP code
<?php
echo 'john';
?>
When I run this code on a AVD, the alert does not display the string. I have never seen such a alert getting displayed. The alert displayed inside the success function is shown below.
On inspecting this string, I understood that the length is 0.
I was able to reproduce the same issue on browser with a string of 0 characters length.
I'm not sure why the piece of code that is working fine when run on browser but acts weirdly on AVD. The string was getting displayed as expected on browser but not on AVD.
Find below the screenshots of the same code displaying the correct alert on browser.
I want to know the possible reasons of why the string from PHP is getting lost ?
I've never used PhoneGap but since your php file is stored on a different server than the files trying to call it, you will need to enable Cross-Origin Resource Sharing (CORS) (though I can't be sure this is the only issue)
Try adding Header set Access-Control-Allow-Origin "*" in your server's .htaccess file
By default, servers block access to resources like php files when the request comes from a file that is not stored on the same server.
For example, if I have a js file located at http://myfirstwebsite.com/awesome.js and in that file I make an ajax call to http://mysecondwebsite.com/loadstuff.php, the request will be blocked by the server and will produce the following error in the console:
XMLHttpRequest cannot load http://mysecondwebsite.com/loadstuff.php. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://mysecondwebsite.com' is therefore not allowed access.
I'm not sure if you can see this error in PhoneGap or where as I have never used it.
As the warning alludes to, in order to fix this, you must set the 'Access-Control-Allow-Origin' header to allow remote files to access the ones on your server.
Here is a tutorial explaining how to do that on Ubuntu
Just in case that link ever dies, here are the steps (copied right from that site)
Make sure you have the mod_headers Apache module installed. to do this check out /etc/apache2/mods-enabled/ and see if there’s a ‘headers.load’ in there. If there isn’t then just sudo ln -s /etc/apache2/mods-available/headers.load /etc/apache2/mods-enabled/headers.load
Add the Access-Control-Allow-Origin header to all HTTP responses. You can do this by adding the line Header set Access-Control-Allow-Origin "" to the desired section in your configuration file (like the /etc/apache2/sites-available/default file). Saying "" will allow cross-site XHR requests from anywhere. You can say "www.myothersite.com" to only accept requests from that origin.
Reload apache server. sudo /etc/init.d/apache2 reload

Cross Domain XML to Javascript from PHP

I want to send XML data from php(domain A) to a remote javascript file(domain B).
I can't have them on the same domain, and I can't have any other files on on domain B.
I've read about sending a JSONP object from php instead of XML, but as I understood from a tutorial, I would need a php proxy on the same domain as where the javascript file is located. tutorial link
(xhr.open("GET", "xmlproxy.php?url=" + escape(url), true); <= this line kinda tells me, that the xmlproxy.php has to be on the same domain as the actuala javascript)
Any suggestions, on how could I do this?
LATER EDIT AFTER ThW's answer
Now I have the following sample code :
The testlog.php file
<?php header('Access-Control-Allow-Origin: *');
print "<Logs><Log><id>Test Log</id></Log></Logs>";
?>
The javascript function that is called on page load:
function getTestLog() {
alert("Gets here!");
$.ajax({
url: "anotherdomain/testlog.php",
data: requestVars,
dataType: 'xml',
success: function(xml){
alert(xml);
},
error: function (xhr, err) {
alert("Error: " + xhr.readyState + "\nstatus: " + xhr.status + "\nerror:" + err);
alert("responseText: " + xhr.responseText);
}
});
}
The problem is, that it's not getting into the ajax thing
If you control the PHP that outputs the XML you can use CORS.
By default Javascript can only open resources from the domain it was loaded. Other resources have to allow that they can be loaded by a Javascript on a different domain.
To do that add a header to the PHP-Script:
header('Access-Control-Allow-Origin: http://javascript-domain.tld');
Or to allow the loading of the XML from anywhere:
header('Access-Control-Allow-Origin: *');
You're using jQuery and here might be a problem if you're not sending the correct content type from PHP.
header('Content-Type: application/xml');
To validate that it is the Cross Domain that it is blocking the reading open you Javascript console in the browser. It should output an error message. In Firefox it is something like:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at http://domain.tld/path/to/resource. This can be fixed by
moving the resource to the same domain or enabling CORS
If you get the request, it should show up in the Network-Tab of your developer tools and you can validate the HTTP response headers.
Here is simple JS snippet using XHR, it forces the content type.:
var xhr = new XMLHttpRequest;
xhr.overrideMimeType("application/xml");
xhr.addEventListener(
'load',
function (xhr) {
return function () {
if (xhr.status >= 200 && xhr.status < 400) {
console.log(xhr.responseXML);
}
}
}(xhr)
);
xhr.open('GET', 'http://php-domain.tld/script.php');
xhr.setRequestHeader("Accept", "application/xml");
xhr.send();

ajax GET - XMLHttpRequest cannot load

I'm trying to get data from a external api, but
I keep getting the error message:
XMLHttpRequest cannot load... No 'Access-Control-Allow-Origin' header is present on the requested resource.
here is my code:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script type="text/javascript">
(function () {
$.support.cors = true;
$.ajax({
type: "GET", url: "http://zhettoapi.azurewebsites.net/api/Values?product=Coca Cola", success: function (data) {
window.alert("" + data);
//example of setting innerHTML of object
document.getElementById("myElement").innerHTML = "The number is:" + data;
}, error: function (xhr, status, error) {
// Display a generic error for now.
alert("Error: " + xhr + " " + status + " " + error);
}
});
})();
</script>
</head>
<body>
<div id="myElement"></div>
</body>
</html>
Since i can see that use have used azurewebsites mentioned in Get url ( "http://zhettoapi.**azurewebsites**.net/api/Values.... ), and i have some experience on that, i thought of solving your problem, even if this question was not tagged with Azure.
Assumption : You have used WebAPI.And deployed on Azure as website. ( i am sure, it is).
Since you are trying to access Azure Web API url from other domain in form of ajax.get request, it gets blocked because of cross domain ( CORS) security. So first thing here, is to make it(hosted WebAPI project) CORS enabled.
Steps to make it CORS enabled:
Install this - Install-Package Microsoft.AspNet.WebApi.Cors using NuGet
Open the file App_Start/WebApiConfig.cs. Add the following code to the WebApiConfig.Register method.
Next, add the [EnableCors] attribute to the Controller class:
With following params
[EnableCors(origins: "http://zhettoapi.azurewebsites.net", headers: "", methods: "")]
Redeploy your WebAPI project.
SOURCE - http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api
More links - http://www.codeproject.com/Articles/742532/Using-Web-API-Individual-User-Account-plus-CORS-En
Thanks!
Also this tutorial was helpful(describing):
http://www.codeguru.com/csharp/.net/net_asp/using-cross-origin-resource-sharing-cors-in-asp.net-web-api.html

Categories

Resources