I trying to make an ajax request to another domain, it already works, but now I have another problem...
This is my code:
function getChannelMessages(channel) {
jQuery.support.cors = true;
$.ajax(channel, {
cache : true,
type : "get",
data : _channels[channel].request,
global : false,
dataType : "jsonp text xml",
jsonp : false,
success : function jsonpCallback (response) {
console.log(response);
updateChannelRequest(channel);
//getChannelMessages(channel);
}
});
}
As I said, it already works, but the problem is the server returns an XML (Is not my server, is another server from another company - a web service - so I can not change what it returns) and as jsonp expects an json it fails with the error:
SyntaxError: syntax error
<?xml version="1.0"?><ReceiveMessageResponse xmlns="http://q ... />
According to jQuery documentation, adding jsonp text xml should make the magic, converting the response to simple text and then parsing it as XML, but it does not works.
I was already able to make it using YQL, but it has a limit of 10,000 requests per hour, and the system I'm developing will have up to 10 million request per hour. For that same reason, I can not "proxy" in my own server those requests...
FYI: I'm trying to get the newest messages from SQS, so if there is anyway to tell it to return the data as json, it will be easier and better, but I have not find anything either in the documentation...
The plain answer to my question is this: There are only two ways of do this:
Use a proxy. I won't put here all the how-to's to make it, but you can find a lot of information in the web searching for "cors" "cross domains ajax requests" and "yql" (this last is a proxy by Yahoo)
Use CORS. This is Cross-Origin Resource Sharing. That is: activate the server from which you want to get information to sent information to any other domain and to answer to requests from any other domain. To do this you must be the one who manage the server/service.
Those two are the only ways of getting information XML (or any other format) from another domain. To make json cross domain requests:
Use jsonp (Json Padded). I won't explain this (and actually is just extra information since it won't work if the answer from the server is XML - my main problem), cause there is a lot of information on the web.
Unfortunately I was not able to accomplished my goal, cause SQS is not configured to any of this methods... Still, I've got plenty insight of how Cross-Domains Requests works. And I hope this help anyone...
Related
I've seen many examples for JSONP but I can't seem to get any to work for my website. It can generate a JSON code at some url but I can't retrieve it from a different domain. Can you please give me a working example of JSONP that can retrieve data from any JSON file (eg. www.w3schools.com/json/myTutorials.txt).
I may not fully understand, but I just need an explanation, at least, of why if I replace a url with the example above, no data is being pulled.
This is a modified version of the example in the jquery docs using Yahoos public APIs.
$.ajax({
url: "https://query.yahooapis.com/v1/public/yql",
// Tell jQuery we're expecting JSONP
dataType: "jsonp",
// Tell YQL what we want and that we want JSON
data: {
q: "show tables",
format: "json"
},
// Work with the response
success: function( response ) {
console.log( response ); // server response
}
});
Along with a jsbin: https://jsbin.com/tuketa/edit?js,output
The reason for the existence of JSONP is to get around the limitations of CORS rules. For security reasons your browser, in general, is only allowed to communicate to the server it loaded the page from. JSONP was created to get around this by giving the server a callback function with which to pad the JSON data, hence the P in JSONP.
As noted in the comments by jasonscript, it's not any server that can function with JSONP, it has to be configured be able to work with JSONP such as the Yahoo API in the example.
There's many answers out there pointing out the difference between JSON and JSONP. Your question ("...jsonP that can retrieve...") shows that you didn't fully understand the concept. JSONP is a format of answer, as is HTML, XML, JSON. And so the server that responds the request should be able to send it JSONP formatted.
from a different domain... from any json file... it's not possible. The server response it's actually a javascript that wraps a json object.
jsonP is a protocol. the requester (the javascript in the browser) can't request via XHR (ajax) outside the source server:port due the Same-Origin-Policy (SOP).
To bypass the SOP, JSONP born.
The client does not send a XHR request, instead adds a <script> tag to the DOM, with the src attribute pointing to the URL of the jsonP with a parameter (e.g. callback=foo) which tells the name of the local function who receives the JSON as parameter.
Then, the remote server -who understands JSONP- sends a javascript who calls the local function with the JSON as parameter.
Like this example:
Client javascript code:
function foo(data)
{
// do stuff with JSON
}
var script = document.createElement('script');
script.src = '//example.com/path/to/jsonp?callback=foo'
document.getElementsByTagName('head')[0].appendChild(script);
(taken from here)
Server Response:
HTTP/1.1 200 OK
Content-Type: text/javascript
foo({ "key" : "value" });
So, the browser loads the script, calls foo with the json as parameter. Now, You have bypassed the SOP restrictions.
I am attempting to call this web service: http://www.civicapps.org/datasets/restaurant-inspections
Here's my code:
<script>
$(document).ready(function() {
function showInspections() {
var data = $.ajax({
type : 'GET',
url : '//api.civicapps.org/restaurant-inspections/',
async : false,
dataType : 'json',
success: function(data){
if(data.status == "ok"){
alert(data);
}
}
});
}
showInspections();
});
</script>
Firebug Net>XHR shows "200 Status OK" and yet there is no response with the JSON data. Likewise, Console tab shows the same GET request and status but the text for it is in red.
Questions:
Am I failing to receive the response data in JSON due to cross-domain issues i.e. the data should be sent in JSONP rather than JSON? If so, is there a way to get around this solely from my end, assuming the response will not be sent in JSONP?
What does the red text in Firebug console indicate?
Am I failing to receive the response data in JSON due to cross-domain issues i.e. the data should be sent in JSONP rather than JSON?
Yes. JSONP is actually very different than "JSON" (i.e. an AJAX request that returns JSON-formatted data). Even though the responses look very similar and the implementation in jQuery is very similar (just add a 'p'!), the actual architecture of JSONP is very different. In fact, JSONP is not even AJAX (if by AJAX you mean something that uses XMLHttpRequest). JSONP gets around cross-domain issues by using a trick involving a dynamically generated <script> element.
If so, is there a way to get around this solely from my end, assuming the response will not be sent in JSONP?
Fortunately, no. While this may be unfortunate for you, it's fortunate for the web. Because if you could get around cross-domain issues from the client side, the web would be far less secure. Imagine you went to my website and some hidden JavaScript downloaded all your new emails from Gmail, parsed them, then sent them to my server. That would be possible if not for the same-origin policy.
JSONP is nice because it offers a workaround for cross-origin requests that services can opt-in to. If a service wants to be accessible cross-domain, then it can be written in JSONP. This prevents unwitting cross-domain services while allowing for services to volunteer cross-domain availability.
What does the red text in Firebug console indicate?
It probably indicates a violation of the same-origin policy.
I'm trying to validate a feed, using the web service that is in this question.
But browser does not allow me to send a ajax GET request to another server. And there is a one second restriction per each request in that web service, so I can't mirror requests from my server.
This is my current jQuery code:
var reqUrl = "http://validator.w3.org/feed/check.cgi?url=" + encodeURIComponent(theUrl);
$.get(reqUrl, function(data) {
// do something
});
Isn't there any other way?
Ajax calls are not valid across different domains unless you use JSONP. JQuery-ajax-cross-domain is a similar question that may give you some insight. Also as noted by Luis in the comments, JSONP has to also be implemented on the domain that you are getting the data from.
Here is an example for jquery ajax(), but you may want to look into $.getJSON():
$.ajax({
url: 'http://yourUrl?callback=?',
dataType: 'jsonp',
success: processJSON
});
Another option is CORS (Cross Origin Resource Sharing), however, this requires that the other server to enable CORS which most likely will not happen in this case.
I searched google and found this. the third answer says that:
In computing, the same origin policy is an important security concept for a number of browser-side programming languages, such as JavaScript. The policy permits scripts running on pages originating from the same site to access each other's methods and properties with no specific restrictions, but prevents access to most methods and properties across pages on different sites.(source)
you'd better see the answers of this question.
I think you can't use JSONP because you haven't any access to W3C script.
Update (explanations)
I the question I linked to there is another way that I can explain it to you. if you set Access-Control-Allow-Origin header to * as the answer said you can send requests to another domains. and to use it easily in an MVC application you can see this solution. Good luck
Update2
to allow just http://validator.w3.org/ you just should set Access-Control-Allow-Origin to http://validator.w3.org/
for more details as answer said go here.
As said you can use JSONP but the endpoint must also implement it, And its only used if you are requesting json data from the call. It looks like you are retrieving html.
You can also implement a simple proxy in your domain that pulls the data from the external location and serves it to the ajax call. You can develop a simple proxy in php using for instance CURL.
Make sure you understand the implications of this security wise making sure for instance that you protect your proxy to only make calls to that external url (whitelisting).
Update: I just noticed you cannot use the proxy solution. And after following the link you have suggested I have came across CORS, which I didnt event know about. So apparentry you can set some headers when you are serving the pages in your domain that will instruct the browser that requests to some domains can be done.
Check this page for how to implement it:
http://enable-cors.org/
I have read that you might have to tweak it a bit to work with IE but it seems that all browsers are now implementing it.
I know this is an old question, but I myself have been trying to create AJAX requests to validator.w3.org as well, hit the exact same issues and stumbled on this SO question.
However, I did find a solution;
As people have already stated, the main problem here is that the server must issue valid CORS headers, i.e.
Access-Control-Allow-Origin: *
I used Fiddler to check the response headers from validator.w3.org and sure enough, the headers were not set. However, they also have another tool that does at validator.w3.org/nu/.
Here is an example: http://codepen.io/DDN-Shep/pen/ogdGgO/
$('form').on('submit', function(e) {
e.preventDefault();
var data = new FormData(this);
$.ajax({
url: 'http://validator.w3.org/nu/', // Trailing '/' is important or you get a 301 HTTP response status code
type: 'POST',
data: data,
processData: false, // Required for jQuery & FormData
contentType: false, // Set by FormData, required by the server
success: function(data, status, xhr) { /* TODO */ },
error: function(xhr, status, error) { /* TODO */ },
complete: function(xhr, status) { /* TODO */ }
});
});
If you are ever unsure whether or not a server allows CORS, you can use this very helpful online tool;
test-cors.org = http://client.cors-api.appspot.com/client
I have to send (and receive) certain data to a server using JQuery and JSON.
Works so far, but not cross domain, and it has to be cross domain.
I looked how to solve this and found JSONP. As far as I see, using JSONP I have to send the callback and the data using GET (JQuery allows to use "POST" as method, but when I inspect web traffic I see it is sending actually GET and everyting as parameter).
JSONP also requires changes in the server, because they are expecting a POST request with JSON data, and they have to implement something to process the JSONP GET request.
So I'm wondering what's the difference between this and sending the data as key value parameters in GET request?
Is the difference the possibility to use a callback? Or what exactly?
Sorry a bit lost... thanks in advance
JSONP is not a form submission. It is a way of telling the server via a GET request how to generate the content for a script tag. The data returned is a payload of JavaScript (not just JSON!) with a function call to a callback which you (by convention) reference in the GET request.
JSONP works because it is a hack that doesn't use AJAX. It isn't AJAX and you should not confuse it for such because it does not use a XMLHttpRequest at any point to send the data. That is how it gets around the Same Origin Policy.
Depending on the browsers you have to support, you can implement Cross-Origin Resource Sharing headers on the server side which will let you use normal AJAX calls across trusted domains. Most browsers (IE8, Firefox 3.5+, etc.) will support CORS.
Another solution you can use if you don't want to use CORS or JSONP is to write a PHP script or Java servlet that will act as a proxy. That's as simple as opening a new connection from the script, copying all of the incoming parameters from your AJAX code onto the request and then dumping the response back at the end of your script.
I found an answer that worked for me with the cross-domain issue and JSON (not JSONP).
I simply used:
header('Access-Control-Allow-Origin: *');
inside my json file (file.php) and called it like this:
var serviceURL = 'http://your-domain.com/your/json/location.php'
$.getJSON(serviceURL,function (data) {
var entries = data;
//do your stuff here using your entries in json
});
BTW: this is a receiving process, not sending.
I'm jusing jQuery's $.getJSON() function to return a short set of JSON data.
I've got the JSON data sitting on a url such as example.com.
I didn't realize it, but as I was accessing that same url, the JSON data couldn't be loaded. I followed through the console and found that XMLHttpRequest couldn't load due to Access-Control-Allow-Origin.
Now, I've read through, a lot of sites that just said to use $.getJSON() and that would be the work around, but obviously it didn't work. Is there something I should change in the headers or in the function?
Help is greatly appreciated.
It's simple, use $.getJSON() function and in your URL just include
callback=?
as a parameter. That will convert the call to JSONP which is necessary to make cross-domain calls. More info: http://api.jquery.com/jQuery.getJSON/
You may well want to use JSON-P instead (see below). First a quick explanation.
The header you've mentioned is from the Cross Origin Resource Sharing standard. Beware that it is not supported by some browsers people actually use, and on other browsers (Microsoft's, sigh) it requires using a special object (XDomainRequest) rather than the standard XMLHttpRequest that jQuery uses. It also requires that you change server-side resources to explicitly allow the other origin (www.xxxx.com).
To get the JSON data you're requesting, you basically have three options:
If possible, you can be maximally-compatible by correcting the location of the files you're loading so they have the same origin as the document you're loading them into. (I assume you must be loading them via Ajax, hence the Same Origin Policy issue showing up.)
Use JSON-P, which isn't subject to the SOP. jQuery has built-in support for it in its ajax call (just set dataType to "jsonp" and jQuery will do all the client-side work). This requires server side changes, but not very big ones; basically whatever you have that's generating the JSON response just looks for a query string parameter called "callback" and wraps the JSON in JavaScript code that would call that function. E.g., if your current JSON response is:
{"weather": "Dreary start but soon brightening into a fine summer day."}
Your script would look for the "callback" query string parameter (let's say that the parameter's value is "jsop123") and wraps that JSON in the syntax for a JavaScript function call:
jsonp123({"weather": "Dreary start but soon brightening into a fine summer day."});
That's it. JSON-P is very broadly compatible (because it works via JavaScript script tags). JSON-P is only for GET, though, not POST (again because it works via script tags).
Use CORS (the mechanism related to the header you quoted). Details in the specification linked above, but basically:
A. The browser will send your server a "preflight" message using the OPTIONS HTTP verb (method). It will contain the various headers it would send with the GET or POST as well as the headers "Origin", "Access-Control-Request-Method" (e.g., GET or POST), and "Access-Control-Request-Headers" (the headers it wants to send).
B. Your PHP decides, based on that information, whether the request is okay and if so responds with the "Access-Control-Allow-Origin", "Access-Control-Allow-Methods", and "Access-Control-Allow-Headers" headers with the values it will allow. You don't send any body (page) with that response.
C. The browser will look at your response and see whether it's allowed to send you the actual GET or POST. If so, it will send that request, again with the "Origin" and various "Access-Control-Request-xyz" headers.
D. Your PHP examines those headers again to make sure they're still okay, and if so responds to the request.
In pseudo-code (I haven't done much PHP, so I'm not trying to do PHP syntax here):
// Find out what the request is asking for
corsOrigin = get_request_header("Origin")
corsMethod = get_request_header("Access-Control-Request-Method")
corsHeaders = get_request_header("Access-Control-Request-Headers")
if corsOrigin is null or "null" {
// Requests from a `file://` path seem to come through without an
// origin or with "null" (literally) as the origin.
// In my case, for testing, I wanted to allow those and so I output
// "*", but you may want to go another way.
corsOrigin = "*"
}
// Decide whether to accept that request with those headers
// If so:
// Respond with headers saying what's allowed (here we're just echoing what they
// asked for, except we may be using "*" [all] instead of the actual origin for
// the "Access-Control-Allow-Origin" one)
set_response_header("Access-Control-Allow-Origin", corsOrigin)
set_response_header("Access-Control-Allow-Methods", corsMethod)
set_response_header("Access-Control-Allow-Headers", corsHeaders)
if the HTTP request method is "OPTIONS" {
// Done, no body in response to OPTIONS
stop
}
// Process the GET or POST here; output the body of the response
Again stressing that this is pseudo-code.