Ajax calls to subdomain - javascript

I have one server located at example.com running apache, serving my static html files.
I also have a json service located at api.example.com running python with cherrypy.
The user requests example.com and get the index html page. On that page I make an ajax request with jquery to the json service. document.domain returns example.com
$.ajax({
type: 'GET',
url: 'http://api.example.com/resource/',
dataType: 'json',
success: successCallback,
error: errorHandler
});
However, I can't see the response body for the ajax request in firebug. This leads me to believe that the browser (FF) doesn't support this.
What are the best methods to achieve this? I would prefer not to use any proxying on the apache backend for example.com if possible.

You can also use JSONP by adding callback=? to the end of the url. jQuery already knows how to handle these type of requests but it does require some server side changes to handle the callback param.

AJAX request is only supported on the same domain. However, you can write an http proxy in your preferred scripting language and make calls to that http proxy. You can check out this little tutorial on an AJAX proxy written in php.

try changing your domain in your sub-domain, like this
<script type="text/javascript">
document.domain = 'example.com';
</script>
if does not work, change your document.domain in your domain page too.

As far as I know, you can't do AJAX cross-domain.
Why is cross-domain Ajax a security concern?
Though I guess you could do an IFRAME workaround
Cross Sub Domain Javascript

Use document.domain to make the domain be the top level domain instead of the subdomain.
document.domain="example.com"
This is described in detail on MDN.

Related

Scrape info from external XML url with jQuery

I need to scrape/parse some info from an external XML file (xml hosted on other domain) and place that info on my site.
I tried this, and didn't succeed:
jQuery(document).ready(function()
{
jQuery.ajax({
type: 'GET',
url: 'http://42netmedia.com/smart/signal_onAir10.xml',
crossDomain: true,
dataType: 'jsonp',
success: parseXml
});
});
function parseXml(xml)
{
jQuery(xml).find('nowOnAirTitle').each(function()
{
jQuery(".my-site-element").append(jQuery(this).find('nowOnAirTitle').text());
});
}
I hope I managed to explain properly.
PS. I am using jQuery because my site is hosted on WordPress
The short answer is that you cannot do what you're trying to do from Javascript running in a browser.
The same origin policy will block AJAX requests for URLs on different domains. There are a couple of exceptions to this policy:
If the target server supports CORS, it can indicate that cross-origin requests are OK. The URL you are trying to reach is on a server that does not support CORS.
If the target server supports JSONP, your script can retrieve data from the target server by using a <script> tag in your page with a src attribute pointing to the target URL and including a callback parameter to tell the server to wrap the data in a javascript function that returns the data. The URL you are trying to reach is on a server that does not support JSONP.
Yes, jQuery does allow you to make a JSONP request across to the other domain, but the response is not Javascript but XML. Your browser is trying to execute the XML as if it was Javascript and fails with a syntax error.
Any solution to this will require server-side support on the server which hosts your code. You could set up a proxy URL on your web server, but you'd need to do that very carefully because you don't want your server to be used as an open proxy. You could also use a cron job to grab the URL using curl and save it to a static file on your server, but that's probably a bit rude.

HTML JAVASCRIPT 403 FORBIDDEN ERROR [duplicate]

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.

AJAX request gets "No 'Access-Control-Allow-Origin' header is present on the requested resource" error

I attempt to send a GET request in a jQuery AJAX request.
$.ajax({
type: 'GET',
url: /* <the link as string> */,
dataType: 'text/html',
success: function() { alert("Success"); },
error: function() { alert("Error"); },
});
However, whatever I've tried, I got XMLHttpRequest cannot load <page>. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:7776' is therefore not allowed access.
I tried everything, from adding header : {} definitions to the AJAX request to setting dataType to JSONP, or even text/plain, using simple AJAX instead of jQuery, even downloading a plugin that enables CORS - but nothing could help.
And the same happens if I attempt to reach any other sites.
Any ideas for a proper and simple solution? Is there any at all?
This is by design. You can't make an arbitrary HTTP request to another server using XMLHttpRequest unless that server allows it by putting out an Access-Control-Allow-Origin header for the requesting host.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
You could retrieve it in a script tag (there isn't the same restriction on scripts and images and stylesheets), but unless the content returned is a script, it won't do you much good.
Here's a tutorial on CORS:
http://www.bennadel.com/blog/2327-cross-origin-resource-sharing-cors-ajax-requests-between-jquery-and-node-js.htm
This is all done to protect the end user. Assuming that an image is actually an image, a stylesheet is just a stylesheet and a script is just a script, requesting those resources from another server can't really do any harm.
But in general, cross-origin requests can do really bad things. Say that you, Zoltan, are using coolsharks.com. Say also that you are logged into mybank.com and there is a cookie for mybank.com in your browser. Now, suppose that coolsharks.com sends an AJAX request to mybank.com, asking to transfer all your money into another account. Because you have a mybank.com cookie stored, they successfully complete the request. And all of this happens without your knowledge, because no page reload occurred. This is the danger of allowing general cross-site AJAX requests.
If you want to perform cross-site requests, you have two options:
Get the server you are making the request to to either
a. Admit you by putting out a Access-Control-Allow-Origin header that includes you (or *)
b. Provide you with a JSONP API.
or
Write your own browser that doesn't follow the standards and has no restrictions.
In (1), you must have the cooperation of the server you are making requests to, and in (2), you must have control over the end user's browser. If you can't fulfill (1) or (2), you're pretty much out of luck.
However, there is a third option (pointed out by charlietfl). You can make the request from a server that you do control and then pass the result back to your page. E.g.
<script>
$.ajax({
type: 'GET',
url: '/proxyAjax.php?url=http%3A%2F%2Fstackoverflow.com%2F10m',
dataType: 'text/html',
success: function() { alert("Success"); },
error: function() { alert("Error"); }
});
</script>
And then on your server, at its most simple:
<?php
// proxyAjax.php
// ... validation of params
// and checking of url against whitelist would happen here ...
// assume that $url now contains "http://stackoverflow.com/10m"
echo file_get_contents($url);
Of course, this method may run into other issues:
Does the site you are a proxy for require the correct referrer or a certain IP address?
Do cookies need to be passed through to the target server?
Does your whitelist sufficiently protect you from making arbitrary requests?
Which headers (e.g. modify time, etc) will you be passing back to the browser as your server received them and which ones will you omit or change?
Will your server be implicated as having made a request that was unlawful (since you are acting as a proxy)?
I'm sure there are others. But if none of those issues prevent it, this third method could work quite well.
you can ask the developers of that domain if they would set the appropriate header for you, this restriction is only for javascript, basically you can request the ressource from your server with php or whatever and the javascript requests the data from your domain then
Old question, but I'm not seeing this solution, which worked for me, anywhere. So hoping this can be helpful for someone.
First, remember that it makes no sense to try modifying the headers of the request to get around a cross-origin resource request. If that were all it took, it would be easy for malicious users to then circumvent this security measure.
Cross-origin requests in this context are only possible if the partner site's server allows it through their response headers.
I got this to work in Django without any CORS middleware by setting the following headers on the response:
response["Access-Control-Allow-Origin"] = "requesting_site.com"
response["Access-Control-Allow-Methods"] = "GET"
response["Access-Control-Allow-Headers"] = "requesting_site.com"
Most answers on here seem to mention the first one, but not the second two. I've just confirmed they are all required. You'll want to modify as needed for your framework or request method (GET, POST, OPTION).
p.s. You can try "*" instead of "requesting_site.com" for initial development just to get it working, but it would be a security hole to allow every site access. Once working, you can restrict it for your requesting site only to make sure you don't have any formatting typos.

Jquery not working for external domains

I have a function in Jquery, that try get html from an page:
$.ajax({
type:'GET',
url: 'http://www.google.com',
success: function( data ) {
alert( data );
}
});
why does not works?
in firebug I see the communication headers.
you are violating SOP. To avoid SOP uou would likely need a server side script (on your host) to load the external url and return the data to your client side script, or use a service that provides a JSONP results.
Well, for security reasons, Javascript don't allow a page to load a page from external domains. These security reasons are to prevent users from form hijacking, xss attacks etc. If you still want to load external pages, you can use iframes, else you will need an openId kind of thing in your backend.
Cross domain $.ajax is not permitted due to security violation. The only cross domain call that you can do in jQuery is JSONP request.
Please read my answer to this question: JavaScript: How do I create JSONP?

Cross-site AJAX requests

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.

Categories