I'm building and iOS application and
trying to get the json data from a url similar to:
example.com/ajax/u.php?callback=jQuery84054761566_1389381628746
Is anyone familiar with these types of callbacks?
Typical HTTP requests in obj-c return 200 status and a null response object with this url.
That's a JSONP callback used for...well, JSONP. JSONP is used on webpages to avoid the 'same origin' restriction. That is, a webpage loaded from a certain domain (say abc.com) cannot call/access resources on a separate domain (say xyz.com).
The way they (web front-end developers) get around this is by using the <script> tag which is exempt from this restriction. However the return of a <script> tag would just be parsed - to cause it to execute something, you tell it a function name that exists in your JavaScript code, in this case, jQuery84054761566_1389381628746.
So instead of returning a regular JavaScript object, say
{key : 'value'}
the server then returns a function invocation
jQuery84054761566_1389381628746({key : 'value'})
and you have, in your webpage JavaScript, the function definition for jQuery84054761566_1389381628746 that does something:
jQuery84054761566_1389381628746 = function(data){
alert(data.key);
};
iOS does not have this same-origin/cross-site restriction so you don't need JSONP - you can call whatever server you want.
Related
In many example code I saw the format of .getJSON() is something like
$.getJSON("url?jsoncallback=?", function(data){
...}
And at back-end the response is written like
$response = $_GET["jsoncallback"]."(".json_encode($orders).")";
echo $reponse
I delete "?jsoncallback=?" from the url and $_GET["jsoncallback"] and square brackets at back-end and it seems that everything still works. So what is the use of that jsoncallback stuff indeed?
If you don't have the jsoncallback=? it will just do normal JSON request not JSONP*. You can do normal JSON request just fine on your own server or a server that sends CORS headers.
* forget about JSONP, this is a fancy name for inserting a script element in your document that runs code from a foreign server but with same authorization as your own scripts. The $_GET["jsoncallback"], makes it a javascript function call like this:
fn({"data": "value"});
This is the code in a script like <script src="http://foreign.org/data?jsoncallback=fn"></script>. As you can see, that's Javascript, not JSON. With this, foreign.org (or someone hacking them) can change their script to do anything with authorization on your page, so be careful when using "JSONP" and prefer CORS JSON.
The callback name is used for JSONP, which is a way to circumvent the same origin policy.
JSON callback can be used to display cross domain data with jQuery. JSONP is used to make cross domain calls since it's not allowed by the same origin policy. Check out the example below.
http://www.9lessons.info/2009/12/display-cross-domain-data-json-callback.html
I am a JSON newbie, but have good experience in PHP and javascript. The question is simple, and the answer might be simpler. I am having trouble sending data from the PHP file on the server, to another PHP file that I have locally which would receive the data in JSON format from the server. What am I doing wrong?
Javascript Frag ( Local )
$(document).ready(function(){
//attach a jQuery live event to the button
$.getJSON('http://www.xpal.com/ws_users.php?action=get_user_data&user_id=33',function(data) {
alert(data); //uncomment this for debug
$('#showdata').html("<p>Username= "+data.username+"<br> Email= "+data.email+"<br> Firstname="+data.firstname+"<br> Lastname="+data.lastname+"</p>");
});
});
PHP Frag (Server #xpal.com) :
$users=new users;
if($_GET['action']=="get_user_data")
{
$user_id=$_GET['user_id'];
$assoc=array(
"username"=>$users->return_username($user_id),
"email"=>$users->return_user_emailid($user_id),
"firstname"=>$users->return_user_firstname($user_id),
"lastname"=>$users->return_user_lastname($user_id)
);
echo json_encode($assoc);
}
Edit :
The error message : XMLHttpRequest cannot load xpal.com/ws_users.php?action=get_user_data&user_id=33. Origin localhost is not allowed by Access-Control-Allow-Origin.
You can't make ajax calls to a different domain that the page is hosted on. See the Same Origin Policy that browsers implement for security reasons.
There is a way to make cross domain ajax calls and it involves using JSONP. Basically, you inject a script tag into your own frame and that script tag points to server endpoint anywhere on the web. Since the src value of a script tag is not restricted by the same origin policy, you can reach that server. But, now you need to have a way to get that result back. That is done using JSONP where you specify in your server request a javascript function that you want the returned javascript to call. That returned javascript can have javascript data in it that is then passed to the desired function. JSONP requires cooperation between both client code and the server code since a normal ajax call might not support the extra part of JSONP. But, with this cooperation of both sides, you can get around the same origin policy for server endpoints that support JSONP.
As already explained in the other answers, this doesn't work because of the Same Origin Policy.
Now, JSONP (see jfriend00's answer) is one way around it, but it has its drawbacks. (see the end of this page).
There is another way around it: and that is have PHP query the remote server and send a response back to the client. See this page:
Cross domain AJAX querying with jQuery
The main drawback of this method is that all the traffic will go through your server, since you have to call the remote page, fetch the response and send the response back to the client.
To use jsonp, as other suggest, you must either put "callback=?" at the end of your URL, or use $.ajax() and specify the dataType is jsonp. Examples here.
Its called the Same Origin Policy. In short: the domain that your code is on, is the only domain your javascript can communicate with (by default)
JQuery won't get json?
You could run a php script on your own server if that is an option.
This:-
<?php
$details = file_get_contents('http://www.xpal.com/ws_users.php?action=get_user_data&user_id=33');
var_dump(json_decode($details));
returned this:-
object(stdClass)[1]
public 'username' => string 'sniper' (length=6)
public 'email' => string 'ajithsubramanian#gmail.com' (length=26)
public 'firstname' => string 'Ajith' (length=5)
public 'lastname' => string 'Ravi' (length=4)
Does that put you on the right path? You could do an AJAX call to a script based on this on your server.
You should take a look at CORS and its implementation.
In your case, the possible solution would be to use header(Access-Control-Allow-Origin:http://localhost) in your php file. Replace localhost with the domain which is restricted by SOP.
A good reference on CORS can be found at https://developer.mozilla.org/en/HTTP_access_control .
You could use the same jQuery to make a cross-domain request, Just check the link cross-domain request, they have demo how to implement the cross-domain request...
In your code, Make sure that the following things are correct,
the www.xpal.com output should be in json format
if there is any error in your output, jsonp technique doesnt display error (poor error handling).
Your json output should be covered with echo $_GET['callback']." ".json_encode($array).")"; as in the mentioned link.
So far when creating AJAX requests I have been posting to a separate PHP file. Is it possible to create a jQuery AJAX request that calls a PHP function rather than posts to a separate page?
If you could send me any examples or documentation would be great.
I believe there's a fundamental misunderstanding of how the technology works here.
AJAX (Javascript), Flash, or any client-sided technology cannot directly call PHP functions (or other languages running on the server).
This is true for going the other way around as well (eg: PHP can't call JS functions).
Client and server codes reside on different machines, and they communicate through the HTTP protocol (or what have you). HTTP works roughly like this:
Client (eg: browser) sends a REQUEST -> Server processes request and sends a RESPONSE -> Client gets and displays and/or processes the response
You have to see these requests and responses as messages. Messages cannot call functions on a server-side language directly 1, but can furnish enough information for them to do so and get a meaningful message back from the server.
So you could have a handler that processes and dispatches these requests, like so:
// ajax_handler.php
switch ($_POST['action']) {
case 'post_comment':
post_comment($_POST['content']);
break;
case '....':
some_function();
break;
default:
output_error('invalid request');
break;
}
Then just have your client post requests to this centralized handler with the correct parameters. Then the handler decides what functions to call on the server side, and finally it sends a response back to the client.
1 Technically there are remote procedure calls (RPCs), but these can get messy.
AJAX requests call a URL (make a HTTP request), not a file, in most cases the URL is translated by the server to point at a file (or a php script in your case), but everything that happens from the HTTP request to the response that is received is up to you (on your server).
There are many PHP frameworks that map URL's to specific php functions, AJAX is just an asynchronous way to access a URL and receive a response.
Said URL CAN trigger the server to call a specific function and send back a response. But it is up to you to structure your URL's and server side code as such.
If you're asking whether you can call any arbitrary PHP function with AJAX the answer is no*, for obvious security reasons (in addition to the technical reasons). You could make a PHP script that does different things depending on what parameter it's given (for example, execute a single function) if you don't want to create multiple separate files.
*Although you could make a script that would execute any arbitrary PHP command coming from the client, but that would be very, very, very unwise.
Short answer is "no" but the real answer is that you can fake it. NullUserException's answer is good. You create a server that will take the function name and its parameters. Then the server executes the function, and returns the value.
This was done a while back via a protocol called XML-RPC. There was also an effort called JSON-RPC that used some JS techniques.
One things that's cool about JS is that you can do things like this:
var base64_decode = create_remote_call('base64_decode');
function create_remote_call(name) {
return function(x) {
jQuery.getJSON('url/server.php',
{func:name,arg:x},
function(d){return d;});
}
}
A call to base64_decode('sarefdsfsaes') will make a ajax request and return the value.
That code probably won't work because it hasn't been tested, but it's a function that produces a function that will call the server, and then return the value. Handling more than one argument requires more work.
All that said... in my experience, it's usually good to make all network communications explicit instead of disguising it as a regular function.
you may achieve the same result using a bridge, like my phery library http://phery-php-ajax.net you can call PHP functions directly from Javascript and deal with the value. The AJAX is bound to DOM elements, so you can manipulate the calling DOM or just use jQuery from the PHP side. An example would be:
Phery::instance()->set(array(
'phpfunction' => function(){
return PheryResponse::factory()->jquery('body')->addClass('whoops');
}
))->process();
and in the javascript side (or HTML)
phery.remote('phpfunction');
the equivalent to the https://stackoverflow.com/a/7016986/647380 from John Kawakami answer, using phery is:
function base64($data){
return !empty($data['encode']) ? base64_encode($data['content']) : base64_decode($data['content']);
}
Phery::instance()->set(array(
'base64' => 'base64'
))->process();
function base64(content, decode, output){
phery.remote('base64', {'content': content, 'encode': decode ? 1 : 0}, {'type':'text'}).done(output);
}
base64('asdf', false, function(data){
console.log(data); // or assign to some variable
});
since AJAX is asynchronous and you can't just return a value from the AJAX call, you need a callback, but this would suffice.
I'm using PHP to pull the events from a FullCalendar as a JSON feed but I need to support multiple domains. I need a querystring variable to specify which calendar to pull events from... is this causing a problem? Here's the FullCalendar init code:
$('#full-calendar".$id."').fullCalendar({
editable: false,
events:'http://www.mydomain.com/resources/include/calendar-events.php?cal=".$id."',
loading: function(bool) {
if (bool) $('#loading').show();
else $('#loading').hide();
}
});
The documentation says "If you need to access a feed that is in a different domain, you can use JSONP with a ? in your URL (see the JSONP discussion in $.ajax)."
But I'm not exactly sure how to do that.
Thanks for your help in advance.
Well at a high level, JSONP lets you specify the name of a callback function that you want called when the AJAX request returns with data. HTTP GET operations can happen across different domains, (when you embed an image from a different host, you are creating an HTTP GET). POST (and PUT, DELETE etc) are limited to the same domain as the document (this is called the Same Origin Policy). JSONP, adds an extra parameter (usually 'callback') with the value of a JavaScript function in your document (the callback function). The sever sending the JSON needs to know to extract the value for that parameter. Your request might look like this:
GET http://ical.example.com/cal.json?callback=_calDraw
The cal.json servlet will return this
_calDraw({event:{date:'12/25/2010',title:'Jason\'s birthday'}});
Now this bit of JavaScript references the callback function you passed into it, but without a corresponding
function _calDraw(data) {
//render stuff
}
The returned data will just fail. It's important that you have some level of trust with any server you are making a JSONP call to, because you are giving them permission to execute JavaScript in your document (they don't have to return something valid).
Hope this helps!
Help, if you can-
The situation:
http://foobar.com includes a remotely hosted javacript file (http://boobar.com/stuff.js).
The goal is to just get an alert from the remotely hosted php script on foobar.com
I have tried the following code in stuff.js:
$.ajax({
type: "GET",
url: "http://www.boobar.com/script.php?callback=?",
dataType: 'jsonp',
success: function(result) { alert(result); }
});
No luck.
$.getJSON("http://www.boobar.com/script.php?jsonp=?",
function(data) { alert(data); }
);
Also no luck.
On the php side I have tried both the following:
return json_encode(array(0 => 'test'));
echo json_encode(array(0 => 'test'));
In Firefox I get a security error. I understand that it thinks I'm violating the security model. However, according to the jquery documentation, I should be able to accomplish this.
The error seems to be a security feature of the Same Origin Policy: to simplify, you can only make AJAX requests for stuff on the originating server (http://foobar.com). One way around this is to make a simple facade on the originating server, e.g.:
<?php
// this file resides at http://foobar.com/getstuff.php
echo file_get_contents('http://www.boobar.com/script.php?callback=?'
. $possibly_some_other_GET_parameters );
?>
Then, from foobar.com, you can make an AJAX request for http://foobar.com/getstuff.php (which in turn makes a HTTP GET request from your web server to boobar.com and sends it back to the browser).
To the browser, the request goes to the origin server, and is allowed (the browser has no way of knowing that the response comes from somewhere else behind the scene).
Caveats:
the PHP config at foobar.com must have allow_url_fopen set to "1". Although this is the default setting, some servers have it disabled.
the request to www.boobar.com is made from foobar.com server, not from the browser. That means no cookies or user authentication data are sent to www.boobar.com, just whatever you put into the request URL ("$possibly_some_other_GET_parameters").
You can get data from another server asynchronously using script tags and json:
<script type="text/javascript" src="http://somesite.com/path/to/page/"></script>
You can use this to dynamically load a remote javascript (by created a new script element and setting the src attribute, then loading into the DOM), which could set a variable. However, you need to really trust the remote site, because the JS will be evaluated without any precondition.
There is a method called window.name transport or window.name method which uses a general browser bug(not sure if this is a bug actually). You make the request through an iFrame and the loaded page puts the information you need to the "name" property of the JavaScript window object of itself.
This method uses a "blank.htm" since it first navigates to the target page and then goes back to the blank.htm page to overcome the "same origin policy" restriction.
Dojo have implemented this and you can find a more detailed explanation here.
Also I have implemented a cross-domain XMLHttpRequest object based on this method in the library I have written which can be found here.
You may not be able to use the library since it will need 1 or 2 additional libraries which can be found here.
If you need further help in implementing it in your style, I'll try to do my best.
So what I ended up doing, since it was just a GET - no data need to be retrieved - I used JQuery to create a hidden iframe with the URL including the variables I wanted to pass set as the source. Worked like a charm. To all who provded feedback - Thanks!
How about this !! Using a php proxy.
Cross-Domain AJAX calls using PHP
http://www.phpfour.com/blog/2008/03/cross-domain-ajax-using-php/
jQuery .ajax also has a setting 'crossDomain'.
http://api.jquery.com/jQuery.ajax/
crossDomain (default: false for same-domain requests, true for cross-domain requests)
Type: Boolean
If you wish to force a crossDomain request (such as JSONP) on the same domain, set the value of crossDomain to true. This allows, for example, server-side redirection to another domain. (version added: 1.5)