This question already has answers here:
What is JSONP, and why was it created?
(10 answers)
Closed 7 years ago.
As you know, the security of the web browser disallows making of cross domain requests. I read a book which says that you should use XMLHTTPRequest only if you can put the files on the server (means put the page you will load to the same requested domain). If you can't - you should search for an alternative.
My questions are:
What is the cross domain alternative to XMLHTTPRequest?
What about WebSockets? Does this technology allow cross domain request?
EDIT:
It still isn't clear to me...
For example, I pull my page from www.domain1.com and I need to request javascript from www.domain2.com. So the pulled page should include something like:
<script src="www.domain2.com/script.js"></script>
to avoid cross domain restrictions.
And I can use JSONP, and request will look like:
http://ww.domain1.com/?callback=someFunction.js
But: isn't it the same? I just pull js from another domain! Does it avoid cross domain restrictions?
You can make cross domain requests using the XMLHttpRequest object. This is done using something called "Cross Origin Resource Sharing". See:
http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
Very simply put, when the request is made to the server the server can respond with a Access-Control-Allow-Origin header which will either allow or deny the request. The browser needs to check this header and if it is allowed then it will continue with the request process. If not the browser will cancel the request.
You can find some more information and a working example here:
http://www.leggetter.co.uk/2010/03/12/making-cross-domain-javascript-requests-using-xmlhttprequest-or-xdomainrequest.html
JSONP is an alternative solution, but you could argue it's a bit of a hack.
Do a cross-domain AJAX call
Your web-service must support method injection in order to do JSONP.
Your code seems fine and it should work if your web services and your web application hosted in the same domain.
When you do a $.ajax with dataType: 'jsonp' meaning that jQuery is actually adding a new parameter to the query URL.
For instance, if your URL is http://10.211.2.219:8080/SampleWebService/sample.do then jQuery will add ?callback={some_random_dynamically_generated_method}.
This method is more kind of a proxy actually attached in window object. This is nothing specific but does look something like this:
window.some_random_dynamically_generated_method = function(actualJsonpData) {
//here actually has reference to the success function mentioned with $.ajax
//so it just calls the success method like this:
successCallback(actualJsonData);
}
Check the following for more information
Make cross-domain ajax JSONP request with jQuery
If you're willing to transmit some data and that you don't need to be secured (any public infos) you can use a CORS proxy, it's very easy, you'll not have to change anything in your code or in server side (especially of it's not your server like the Yahoo API or OpenWeather).
I've used it to fetch JSON files with an XMLHttpRequest and it worked fine.
Related
As an example case let's take this url: http://api.duckduckgo.com/?q=computer&format=json (CORS not enabled on this server!)
We can access the contents from this URL from any popular browser as a normal URL, browser has no issues opening this URL nor the server returns any error.
A server-side language like PHP/RoR can fetch the contents from this URL without adding any additional headers or special server settings. I used following PHP code and it simply worked.
$url='http://api.duckduckgo.com/?q=computer&format=json';
$json = file_get_contents($url);
echo $json;
I just started working in javascript framework, AngularJS. I used following code...
delete $http.defaults.headers.common['X-Requested-With'];
var url="http://api.duckduckgo.com/?q=computer&format=json";
$http.get(url)
.success(function(data) {
$scope.results=data;
})
With above AngularJS code, I received following error:
XMLHttpRequest cannot load http://api.duckduckgo.com/?q=computer&format=json. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access.
AngularJS uses JQuery so I tried the same in JQuery with following code:
var url="http://api.duckduckgo.com/?q=computer&format=json";
$.getJSON(url , function( data ) {
console.log(data);
});
This also produced the same error as did AngularJS code.
Then my further research brought me to the point that it's actually not specific to JQuery and AngularJS. Both of these inherit this issue from Javascript!
Here is an excellent resource with explanation of what CORS is and how to handle with it: http://enable-cors.org/index.html.
And also W3C has it official CORS specification: http://www.w3.org/TR/cors/
So my question is not what CORS is. My question is
My understanding is that whether it is a web browser or it is PHP/RoR or it is Javascript frameworks, all make requests to a URL via the same http or https, right? Certainly, yes. Then why http has to be more secure when requests come from javascript? How does http and server know that request is coming from javascript?
When a web browser can open a URL and PHP/RoR (or any server-side language) can access that URL without any extra settings/headers, why can't AngularJS, JQuery (or in a single word javascript) access that URL unless the server has set Access-Control-Allow-Origin header for requesting root?
What's that special feature (that PHP/RoR have and) that is missing in Javascript so that it can't access the same URL in the same browsers that can open that URL without any issue from their address bars?
Just to mention that I am basically an iOS developer and recently started to learn web development, specially AngularJS. So I am curious about what's all this going on and why!
It's disabled from javascript for security reasons. Here's one scenario:
Assume Facebook has a "post message on timeline" api that requires the user to be authenticated.
You are logged into Facebook when you visit badsite.com.
badsite.com uses javascript to call the Facebook api. Since the browser is making a valid request to Facebook, your authentication cookie is sent, and Facebook accepts the message and posts badsite's ad on your timeline.
This isn't an issue from a server, because badsite.com's server doesn't have access to your Facebook authentication cookie and it can't forge a valid request on your behalf.
You remember that all javascript request is handled by browser. So browser detect cross-origin request is easy.
Request from javascript has no difference with PHP/RoR, it is only rejected by browser.
Server code can accept cross-origin javascript request by header "Access-Control-Allow-Origin" because before reject javascript request, browser will send a request "OPTIONS" to server to ask header "Access-Control-Allow-Origin" on response. If value is match with current origin, browser will accept javascript request and send to server.
All browser are implement this policy Same Origin Policy
Please read http://en.wikipedia.org/wiki/Cross-site_scripting, you will get the reason why its prohibited for JavaScript.
This question already has answers here:
What is JSONP, and why was it created?
(10 answers)
Closed 7 years ago.
As you know, the security of the web browser disallows making of cross domain requests. I read a book which says that you should use XMLHTTPRequest only if you can put the files on the server (means put the page you will load to the same requested domain). If you can't - you should search for an alternative.
My questions are:
What is the cross domain alternative to XMLHTTPRequest?
What about WebSockets? Does this technology allow cross domain request?
EDIT:
It still isn't clear to me...
For example, I pull my page from www.domain1.com and I need to request javascript from www.domain2.com. So the pulled page should include something like:
<script src="www.domain2.com/script.js"></script>
to avoid cross domain restrictions.
And I can use JSONP, and request will look like:
http://ww.domain1.com/?callback=someFunction.js
But: isn't it the same? I just pull js from another domain! Does it avoid cross domain restrictions?
You can make cross domain requests using the XMLHttpRequest object. This is done using something called "Cross Origin Resource Sharing". See:
http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
Very simply put, when the request is made to the server the server can respond with a Access-Control-Allow-Origin header which will either allow or deny the request. The browser needs to check this header and if it is allowed then it will continue with the request process. If not the browser will cancel the request.
You can find some more information and a working example here:
http://www.leggetter.co.uk/2010/03/12/making-cross-domain-javascript-requests-using-xmlhttprequest-or-xdomainrequest.html
JSONP is an alternative solution, but you could argue it's a bit of a hack.
Do a cross-domain AJAX call
Your web-service must support method injection in order to do JSONP.
Your code seems fine and it should work if your web services and your web application hosted in the same domain.
When you do a $.ajax with dataType: 'jsonp' meaning that jQuery is actually adding a new parameter to the query URL.
For instance, if your URL is http://10.211.2.219:8080/SampleWebService/sample.do then jQuery will add ?callback={some_random_dynamically_generated_method}.
This method is more kind of a proxy actually attached in window object. This is nothing specific but does look something like this:
window.some_random_dynamically_generated_method = function(actualJsonpData) {
//here actually has reference to the success function mentioned with $.ajax
//so it just calls the success method like this:
successCallback(actualJsonData);
}
Check the following for more information
Make cross-domain ajax JSONP request with jQuery
If you're willing to transmit some data and that you don't need to be secured (any public infos) you can use a CORS proxy, it's very easy, you'll not have to change anything in your code or in server side (especially of it's not your server like the Yahoo API or OpenWeather).
I've used it to fetch JSON files with an XMLHttpRequest and it worked fine.
This question already has answers here:
Ways to circumvent the same-origin policy
(8 answers)
Closed 9 years ago.
Recently I came across the following statement: "All
Ajax calls to an XML data file must come from the same domain or the request will fail.", can anyone help me understanding this since I can't make much out of it.
Let's say your site, including the Javascript that will start the AJAX is hosted at site1.com.
The AJAX will request a file called file.xml whose address is site2.com/file.xml.
This request site1.com ---> site2.com voilates the same origin policy because the 2 are on a different domain.
The way around this?
Easiest solution is to host file.xml on site1.com, if you can?
You can request a URL on your domain site.com/getMeThatAwesomeFile which executes some server side code to grab the file's contents and returns it to you
You can use a reverse proxy so site2.com/file.xml actually resolves to something on your domain.
You can use JSONP but there are some limitations (Only 'GET' verbs allowed and data should be placed inside the function from server). The very first thing JSONP is not an ajax call, it downloads the script and calls the jsonp function and in that function the data is passed.
e.g. If you use JSONP, then it would be like
<script type='text/javascript' src='cross-domain-url'>jsonpFunction(data)</script>
From the server, you must get the response like jsonpFunction({'name':'abc'}), so after getting this response, your declared jsonpFunction will be called and you will be able to achieve this {'name':'abc'} object.
I know it's possible to load any kind of document from any domain from JavaScript (without necessarily being able to peek at its content), but it usually concerns regular GET requests. What about POST?
Is it possible to make an HTTP POST request from JavaScript to any domain name? (I'm specifically interested in form submissions.)
If so, how?
As per some answers on a nearby question, «HTTP GET request in JavaScript?», you might use XMLHttpRequest, since, according to the docs, the POST method is supported, too.
http://www.w3.org/TR/XMLHttpRequest/
https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest
A sample code from the above w3.org document:
function log(message) {
var client = new XMLHttpRequest();
client.open("POST", "/log");
client.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
client.send(message);
}
However, it would seem like in order for it to work with POST requests to domains unrelated to yours (where instead of "/log", a complete http or https URL is specified), the Cross-Origin Resource Sharing may have to be supported and enabled on the target server, as per https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS#Simple_requests.
So, it seems like, at least through XMLHttpRequest, you cannot make form submissions through POST requests (in fact, looks like even GET requests won't fly, either).
I need to make an AJAX request from a website to a REST web service hosted in another domain.
Although this is works just fine in Internet Explorer, other browsers such as Mozilla and Google Chrome impose far stricter security restrictions, which prohibit cross-site AJAX requests.
The problem is that I have no control over the domain nor the web server where the site is hosted. This means that my REST web service must run somewhere else, and I can't put in place any redirection mechanism.
Here is the JavaScript code that makes the asynchronous call:
var serviceUrl = "http://myservicedomain";
var payload = "<myRequest><content>Some content</content></myRequest>";
var request = new XMLHttpRequest();
request.open("POST", serviceUrl, true); // <-- This fails in Mozilla Firefox amongst other browsers
request.setRequestHeader("Content-type", "text/xml");
request.send(payload);
How can I have this work in other browsers beside Internet Explorer?
maybe JSONP can help.
NB youll have to change your messages to use json instead of xml
Edit
Major sites such as flickr and twitter support jsonp with callbacks etc
The post marked as the answer is erroneous: the iframes document is NOT able to access the parent. The same origin policy works both ways.
The fact is that it is not possible in any way to consume a rest based webservice using xmlhttprequest. The only way to load data from a different domain (without any framework) is to use JSONP. Any other solutions demand a serverside proxy located on your own domain, or a client side proxy located on the remote domain and som sort of cross-site communication (like easyXDM) to communicate between the documents.
The fact that this works in IE is a security issue with IE, not a feature.
Unfortunately cross-site scripting is prohibited, and the accepted work around is to proxy the requests through your own domain: do you really have no ability to add or modify server side code?
Furthermore, the secondary workaround - involving the aquisition of data through script tags - is only going to support GET requests, which you might be able to hack with a SOAP service, but not so much with the POST request to a RESTful service you describe.
I'm really not sure an AJAX solution exists, you might be back to a <form> solution.
The not very clear workaround (but works) is using iframe as container for requests to another sites. The problem is, the parent can not access iframe's content, can only navigate iframe's "src" attribut. But the iframe content can access parent's content.
So, if the iframe's content know, they can call some javascript content in parent page or directly access parent's DOM.
EDIT:
Sample:
function ajaxWorkaroung() {
var frm = gewtElementById("myIFrame")
frm.src = "http://some_other_domain"
}
function ajaxCallback(parameter){
// this function will be called from myIFrame's content
}
Make your service domain accept cross origin resource sharing (CORS).
Typical scenario: Most CORS compliant browsers will first send an OPTIONS header, to which, the server should return information about which headers are accepted. If the headers satisfy the service's requirements for the request provided (Allowed Methods being GET and POST, Allowed-Origin *, etc), the browser will then resend the request with the appropriate method (GET, POST, etc.).
Everything this point forward is the same as when you are using IE, or more simply, if you were posting to the same domain.
Caviots: Some service development SDK's (WCF in particular) will attempt to process the request, in which case you need to preprocess the OPTIONS Method to respond to the request and avoid the method being called twice on the server.
In short, the problem lies server-side.
Edit There is one issue with IE 9 and below with CORS, in that it is not fully implemented. Luckily, you can solve this problem by making your calls from server-side code to the service and have it come back through your server (e.g. mypage.aspx?service=blah&method=blahblah&p0=firstParam=something). From here, your server side code should implement a request/response stream model.
Just use a server side proxy on your origin domain. Here is an example: http://jquery-howto.blogspot.com/2009/04/cross-domain-ajax-querying-with-jquery.html
This can also be done using a webserver setup localy that calls curl with the correct arguments and returns the curl output.
app.rb
require 'sinatra'
require 'curb'
set :views,lambda {"views/"+self.name.to_s.downcase.sub("controller","")}
set :haml, :layout => :'../layout', :format => :html5, :escape_html=>true
disable :raise_errors
get '/data/:brand' do
data_link = "https://externalsite.com/#{params[:brand]}"
c = Curl::Easy.perform(data_link)
c.body_str
end
Sending an ajax request to localhost:4567/data/something will return the result from externalsite.com/something.
Another option would be to setup a CNAME record on your own domain to "Mask" the remote domain hostname.