I am new to XHR and am trying to solve a simple use case. I have a web server, from where my javascript would fetch data. But instead of serving the data itself, the server would redirect the javascript XHR request to an alternate location (for example a file on Amazon's S3) to fulfill the request.
This brought me into the world of cross domain XHR, and I am unable to get even a simple example working inspite of reading a bit about it. I am adding "Access-Control-Allow-Origin: *" to the header in my main domain which serves the web page containing the javascript. But it does not work. What am I missing? I need this to work regardless of browser so am looking for something the initial server can do other than serving as a proxy, which defeats the purpose of offloading the request to S3.
Chrome : Gives "Exception: NetworkError: DOM Exception 19" on the
second call.
IE: Shows a warning but opens second url after
confirmation.
Firefox: Just says "Exception: Faliure" on the second
call.
Code follows for test.php:
<?php
header('Content-type: text/html');
header('Access-Control-Allow-Origin: *');
?>
<!DOCTYPE html>
<html>
<header>
<script type="text/javascript">
var request;
var url1 = "data/file.csv";
var url2 = "http://stackoverflow.com/users/1293955/ng-algo";
try
{
if (window.XMLHttpRequest) {
// IE7+, Firefox, Chrome, Opera, Safari
request = new XMLHttpRequest();
}
else {
// code for IE6, IE5
request = new ActiveXObject('Microsoft.XMLHTTP');
}
// load data. 'false' indicates that further script
// is not executed until data is loaded and parsed
alert("Test1 with url: "+url1);
request.open('GET', url1, false);
request.send();
alert(request.responseText);
alert("Test2 with url: "+url2);
request.open('GET', url2, false);
request.send();
alert(request.responseText);
} catch (e) { alert("Exception: "+e.message); }
</script>
</header>
This is a test page
</html>
For any arbitrary request (given the mix of Amazon and Stack Overflow in the question), CORS may not be enough as it's actually the remote server that has to give the permission.
For the 2nd request to succeed, stackoverflow.com would have to include relevant Access-Control-Allow-* headers in their responses that give your website permission to make the request. And whether those are included in the response or not is entirely up to Stack Exchange, in this case.
Also, by including Access-Control-Allow-Origin: * in the response, you're actually allowing other websites to request your page from their origin.
What you may need is a "proxy" script on your server. You can find a generalized solution from Ben Alman:
http://benalman.com/projects/php-simple-proxy/
https://github.com/cowboy/php-simple-proxy
Which would allow:
request.open('GET', 'proxy.php?url=' + encodeURIComponent(url2), false);
Related
I have this code trying to obtain prices from Bloomberg but I can't make it works.
This is the URL:
https://www.bloomberg.com/markets2/api/intraday/BACHOCOB:MM?days=1&interval=2&volumeInterval=15
And my failure code:
<p id="quote"></p>
<script>
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var price= JSON.parse(this.responseText);
document.getElementById("quote").innerHTML = price[0]["previousClosingPriceOneTradingDayAgo"];
}
};
xmlhttp.open("GET", "https://www.bloomberg.com/markets2/api/intraday/BACHOCOB:MM?days=1&interval=2&volumeInterval=15¤cy=MXN", true);
xmlhttp.send();
</script>
Thanks in advance.
What is the excat error message your getting? Is it something like "No 'Access-Control-Allow-Origin' header is present on the requested resource"?
If so, that has nothing to do with JSON.parse as it is a security measure against XSS (Cross Site Scripting). You cannot request web responses from other domains if the server doesn't allows it explicitly.
See https://en.wikipedia.org/wiki/Cross-origin_resource_sharing for more information.
As an additional note: you can work around this. Even if you have no access to the server you could make use of a proxy server, that gets the request for you and uses the appropriate response header to allow your script to make the response. An example would be "corsproxy" from npm (No experience with it. Just a quick google search).
You can get value as below by adding jQuery to your project
$.ajax({
type: "GET",
url: "https://www.bloomberg.com/markets2/api/intraday/BACHOCOB:MM?days=1&interval=2&volumeInterval=15",
dataType: "json",
success: function(getPrice) {
$('#quote').append(getPrice[0].previousClosingPriceOneTradingDayAgo);
}
});
It seems CORS is an issue. Since you are using GET request to an SSL URL, it expects you to send this request from an HTTPS origin. To test your script, use Chrome Browser with CORS extension installed. You shall see the result.
In short, you need an HTTPS origin URL, you might want to try CURL with PHP for a possible solution if SSL is an issue !
I have a site hosted on https:// in which I want to pull data from the site which shows the properties of the shares. The URL which returns the data is:
http://ir1.euroinvestor.com/asp/ir/xmlirmultiiso2.aspx?companyid=281191
The code which I have developed to get the data is as follows:
function GetSharesUpdate(){
// makeing AJAX calls to the web service for getting the share update
var xhr = new XMLHttpRequest(); // Set up xhr request
xhr.open("GET", "http://ir1.euroinvestor.com/asp/ir/xmlirmultiiso2.aspx?companyid=281191", true); // Open the request
xhr.responseType = ""; // Set the type of response expected
xhr.send();
// Asynchronously wait for the data to return
xhr.onreadystatechange = function () {
if (xhr.readyState == xhr.DONE) {
var tempoutput = xhr.responseXML;
alert(tempoutput);
}
}
// Report errors if they happen
xhr.addEventListener("error", function (e) {
console.error("Error: " + e + " Could not load url.");
}, false);
}
I am getting the error on the statement xhr.send(); which is as below:
Mixed Content: The page at 'https://[SiteUrl]' was loaded over HTTPS,
but requested an insecure XMLHttpRequest endpoint
'http://ir1.euroinvestor.com/asp/ir/xmlirmultiiso2.aspx?companyid=281191'.
This request has been blocked; the content must be served over HTTPS.
If I change the URL to https i.e.
https://ir1.euroinvestor.com/asp/ir/xmlirmultiiso2.aspx?companyid=281191
then xhr.send(); is executed without any error but I am getting xhr.responseXML null.
What should I make changes in my code to make it working?
The first problem is you are doing ajax request to non-https domain but your domain has SSL installed.
The second problem is Cross origin request CORS, you will have this problem even you solve first (ie. even you try ajax request from non-http domain).
Since you are requesting data from another website this is most likely to happen unless the requested server is configured to serve requests for you domain
To solve this you need to call the data from your server(proxy server) or have the requested server configured to allow requests from your domain.
See more - https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
Hi I'm working on connecting to an API that is using Layer 7 as an IP authorizer and eGalaxy as a credentials authorizer, when the curl request is sent a line of xml is sent back to me. I'm currently working on localhost, I've implemented the Access-Control-Allow-Origin chrome extension.
My curl request looks as such:
curl https://client-url/eGalaxy.aspx -H 'Content-Type:text/html' --data '<?xml version:"1.0" encoding="UTF-8"?><Envelope><Header><SourceID>0</SourceID><MessageID>131</MessageID><MessageType>Authenticate</MessageType></Header><Body><Authenticate><Username>*username*</Username><Password>*password*</Password><PasswordEncrypted>NO</PasswordEncrypted></Authenticate></Body></Envelope>' --insecure
When I tried to create an ajax request I receive an "Invalid HTTP status code 500" error and "OPTIONS url" which drops down to show:
n.ajaxTransport.k.cors.a.crossDomain.send # jquery-2.1.3.js:4
n.extend.ajax # jquery-2.1.3.js:4
(anonymous function) # VM947:2
InjectedScript._evaluateOn # VM899:895
InjectedScript._evaluateAndWrap # VM899:828
InjectedScript.evaluate # VM899:694
My ajax code is as follows:
$.ajax({
url:'https://client-url/eGalaxy.aspx',
data:'<?xml version:"1.0" encoding="UTF-8"?><Envelope><Header>
<SourceID>0</SourceID><MessageID>131</MessageID>
<MessageType>Authenticate</MessageType></Header><Body>
<Authenticate><Username>*username*</Username>
<Password>*password*</Password>
<PasswordEncrypted>NO</PasswordEncrypted></Authenticate></Body>
</Envelope>',
type:'POST',
contentType:'text/xml',
dataType:'xml',
success: function(data){
},
error: function(){
}
});
Any help with translating into a proper AJAX request would be appreciated!
EDIT: If this makes a difference these are the headers that are returned with the client's xml when the curl is complete(client information deleted)
This application will be made into a widget as well, so it will not be running off of a hosting site.
UPDATE 1: I'm using #KevinB's suggestion that the CORS headers were still not properly added.
Here is my updated JS code, copied from this link:
var url = 'https://client-url/eGalaxy.aspx';
var data = '<?xml version="1.0" encoding="UTF-8"?><Envelope><Header><SourceID>1</SourceID><MessageID>131</MessageID><MessageType>Authenticate</MessageType></Header><Body><Authenticate><Username>*username*</Username><Password>*password</Password><PasswordEncrypted>NO</PasswordEncrypted></Authenticate></Body></Envelope>';
var xhr = createCORSRequest('POST', url);
xhr.send(data);
function createCORSRequest(method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
// Check if the XMLHttpRequest object has a "withCredentials" property.
// "withCredentials" only exists on XMLHTTPRequest2 objects.
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined") {
// Otherwise, check if XDomainRequest.
// XDomainRequest only exists in IE, and is IE's way of making CORS requests.
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
// Otherwise, CORS is not supported by the browser.
xhr = null;
}
return xhr;
}
var xhr = createCORSRequest('GET', url);
if (!xhr) {
throw new Error('CORS not supported');
}
When run with the CORS Chrome extension off I receive an Access-Control-Allow-Origin =! 'null' error. Knowing that CORS needs Access-Control-Allow-Origin header to =! 'null' will this cause problems in the future with making this into a widget that will be put into a Content Manager system?
With it on the origin is set to 'www.evil.com', with the only error in the code being that it says the xhr.send() is an anonymous method. Using breakpoints I can see the xhr in xhr.send() is set to an empty request:
> XMLHttpRequest {response: "", responseText: ""}
Inside the createCORSRequest this line is undefined. I've tested using 'GET' and 'POST' as the method.
xhr.open(method, url, true)
EDIT 2:
Using #Fabiano's approach I've changed the web.config for two versions of what I suspect is my server(?). I'm attaching screenshots of what I've gone through
No luck, so far. Decided to use xhr.AppendHeader:
I decided to use xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
The Network tab Headers for eGalaxy.aspx
There is an error in your XML. You put version:"1.0", and this makes the XML invalid.
Change to version="1.0" and try to make your request. It should work.
This may be the cause for the "Bad request" error.
You can validate your XML here: enter link description here
EDIT: After some research, the problem may be with the headers sent by your server. Your server (or page, .aspx in this case) seems to skip the header you need, the "Access-Control-Allow-Origin: *".
Look at this link: http://enable-cors.org/server.html
This site shows you how to implement it for your server. Since the page you are requesting is called eGalaxy.aspx, then you have 2 ways to implement the headers:
1- Put the line Response.AppendHeader("Access-Control-Allow-Origin", "*"); if the page is a simple ASP.NET application. If it uses Web API 2, you need to implement a different way as it is shown here: http://enable-cors.org/server_aspnet.html
2- Edit the web.config file on the root of your server and add these lines inside the tag:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
For a ASP.NET application, these are the ways you have. The link I mentioned has solutions for other applications, take a look and choose the right one. :)
Note that the value * tells you that your server will accept any cross-origin request. This may lead to a security issue, so the best you can do is to put your domain address instead of *.
I hope it helps!
My app makes an ajax request using CORS, which works in Chrome but not in Firefox. I followed the MDN CORS instructions, but it does not work.
Here's an elided view of my code:
var href = ...
var request = new XMLHttpRequest();
request.open('GET', href, true);
request.setRequestHeader("Accept", "application/json");
request.onload = ...
request.onerror = ...
try {
request.send();
} catch (e) {
console.log(e.message);
}
This results in a NS_ERROR_DOM_BAD_URI exception, with message "Access to restricted URI denied" and code = 1012.
The server is responding with Access-Control-Allow-Origin: http://localhost:13000 which I verified when making the request in Chrome. I'd like to look at the response headers in FF, but the web developer console only shows me the GET requests for the javascript files, and I see no way to examine the headers of the ajax request and response. It would also be nice to verify the pre-flight request, which should result from setting a custom header, but I can't see how to get access to that with the debugger.
I finally found a solution, which seems to indicate a bug in Firefox.
Although not shown in my example code, the server requires HTTP BASIC authentication, which is provided as follows:
request.open('GET', href, true, username, password);
request.withCrednetials = true;
This is in accordance with the MDN specification for XMLHttpRequest.
While this works for Chrome, with Firefox it results in the ajax request not being sent (at least it doesn't appear in the console or net panes of Firebug) and the send() method throwing an exception which claims that the request is being made to an illegal domain.
The following solution works for FF and Chrome:
var href = ...
var username = ...
var password = ...
var request = new XMLHttpRequest();
request.open('GET', href, true); //do not include credentials, or FF will fail to send the request
request.setRequestHeader("Accept", "application/json");
request.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
request.onload = ...
request.onerror = ...
try {
request.send();
} catch (e) {
console.log(e.message);
}
Note that if the username and password are provided as parameters to open(), Firefox fails to send the request and throws an illegal domain exception, even though the credentials were set in the Authorization header.
I'm working on a Chrome extension and I've some issue with a XHR cross-domain. Let me explain: I set right permission in manifest.json for a domain and I make (in my js file) a simple XMLHttpRequest. Request works fine but responseXML field is null. Why? It is not an issue with SOP and responseText correctly contains HTML text of the page requested. How I can parse it? I can't do it with DOMParser().parseFromStringeven with using https://developer.mozilla.org/en/DOMParser implementation, I receive everytime a single.
Some suggestions? My (simple) code is following:
var req = new XMLHttpRequest();
req.open("GET", "http://somedomain.com", true);
req.overrideMimeType("text/xml");
req.setRequestHeader("Content-Type", "text/xml");
req.onload = anonymousFunction;
req.send(null);
Thanks for any replies!