Json request to another domain - php

Im trying to make a request from one server to another with json and php.
my html page:
$.ajax({
type: "POST",
url: "https://api.domain.com/gateway/partners/create_account.ajax.php",
dataType: 'jsonp',
crossDomain: true,
data: { "name" : "Test name"},
success: function(data)
{
console.log(data.responseText);
}
});
My php looks like this:
$name = $_GET['name'];
$data = array("Hello", $name);
echo json_encode($data);
I want to receive on my console: Hello Test name
What did I do wrong?

You are:
Telling jQuery to process the response as JSONP
Writing PHP that will output JSON (not JSONP) … presumably with a text/html content-type.
Trying to make a POST request instead of a GET request. JSONP only supports GET.
Trying to treat the data returned by the request as if it were an XHR object.
The minimal example of a JSONP response would be:
<?php
header("Content-Type: application/javascript");
$name = $_GET['name'];
$data = array("Hello", $name);
echo $_GET['callback'];
echo "(";
echo json_encode($data);
echo ");";
Then you need to alter the JS so that type: "POST" becomes type: "GET" and console.log(data.responseText); becomes console.log(data);
Alternatively, you could use another technique to bypass the same origin policy and still use POST.

The jsonp is a old practice and a insecure one because any one can call to your script. To is very default tor retrieving errors when a jsonp call fails.
You can implement CORS headers in your request, and then you can use just a simple XHR call.
Addeding the header:
Access-Control-Allow-Origin: *
Will fix your issue, but is better use the exact domain instead of the wildcard.

Related

Custom PHP "API" JSON response jQuery

Im not quite sure how to explain this but im experimenting with creating my own API. At the moment things are working quite well by doing cURL requests or jQuery AJAX requests.
My problem is I see using other APIs that you specify you want a JSON response in the arguments root of the jQuery object. With my API I have to specify I want a JSON response in the data argument. How exactly are APIs picking up this JSON argument? Example:
$.ajax({
url: 'url',
type: 'POST',
data: {dataType : 'json'}, //I need this for PHP to know I want a JSON response
dataType: 'json' //how do other APIs grab this on the API side?
}).
done(function(response){
console.log(response);
});
In PHP I can only pickup the data object VIA $_POST. If I remove the data object from the AJAX request I dont get data back. So what should I do in PHP to pickup the "root" dataType argument to know to return JSON?
<?php echo serialize($_POST) ?>
When you set dataType, jQuery sends that info as part of the Accept header, it probably looks something like this: Accept: application/json, text/javascript, */*; q=0.01.
On the PHP side of things, you can access it with the $_SERVER superglobal:
$accept = isset($_SERVER['HTTP_ACCEPT']) ? $_SERVER['HTTP_ACCEPT'] : null;
if ($accept && false !== stripos($accept, 'application/json')) {
// send back JSON
}
If you happen to be using Symfony's HttpFoundation component, it has some nice facilities to deal with Accept headers:
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\AcceptHeader;
$r = Request::createFromGlobals();
$accept = AcceptHeader::fromString($r->headers->get('Accept') ?: '*/*');
if ($accept->has('application/json')) {
// send json
} elseif ($accept->has('application/xml')) {
// send xml
} else {
// send whatever
}

Jquery ajax contentType confused me

I'm using jquery ajax function.
I noticed an issue when I post JSON data to the server.
The type of post data is JSON. So I added the code to specify what I sent was JSON.
contentType: "application/json".
I wrote below code:
var data = {"data": "mytestdata" };
var option = {
url: 'Handler1.ashx',
type: 'POST',
dataType: 'html',
success: function (result) {
alert(result);
},
data: data,
contentType: "application/json"
};
$.ajax(option);
At the server side, I used below code:
string s = context.Request["data"];
But the result s was null.
Logically,setting contentType="application/json" and posting json data are perfect. But it's false.
Also I tried code in php file:
echo $_POST["data"];
PHP says $_POST["data"] doesn't exist.
So I tried to remove the code -- contentType: "application/json".
Now,everything is OK.
But it confused me.
Why needn't set contentType as json when we post the real json data?
You don't need to do contentType: "application/json", when you don't specify content type, it converts the data to be sent in http params, from the json..which are accessible via $_GET, or $_POST params..
But if you want to send json data only..you can try this code on server side to get the data:
<?php
$data = #file_get_contents('php://input');
print_r(json_decode($data));
?>
You were not sending JSON data back. jQuery considers it an error when the ajax content type is set to accept JSON, but malformed JSON is sent back.
echo $_POST['data'] will likely throw the exception "Catchable fatal error: Object of class stdClass could not be converted to string" -- so that actually gets printed out. That's not valid JSON.
What you probably want to do is echo json_encode($_POST['data']);

jQuery JSONP Call towards PHP backend: No HTTP response

Update IV / Current status: I've now confirmed trough another question that the character encoding of the file is fine and not the cause of the problem. I've also tested against another server and the error still persists. It does however work towards localhost.
So to summarize: JSONP call works towards localhost, but when running against external domains the response from the server is empty (no header / no http response code). When copying the requested URL and inserting it directly in a browser, the output is correct with correct formating (utf-8 / json).
Fiddle: http://jsfiddle.net/5SJvp/1/
Update III: I'm now able to get it working succesfully on localhost. However, using the exact same code (both client and server) towards my production domain it still fails. The response from the server is "empty" meaning to say it returns no http status code.
Update II: After some more debugging I noticed that the response does not include an http status code. This probably is the cause of my problem? I assume this means there is something wrong server side, but I cannot for the life of me see where.
Update I: Snip from jQuery where to request seems to halt.
// Do send the request
// This may raise an exception which is actually
// handled in jQuery.ajax (so no try/catch here)
xhr.send( ( s.hasContent && s.data ) || null );
Params (from Firebug)
_ 1356655864905
callback jQuery18308375673194150332_1356655863817
p 0522
pl 12
s false
secret ##############################
u request12341299
Request (from Firebug)
Accept text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01
Accept-Encoding gzip, deflate
Accept-Language nb-no,nb;q=0.9,no-no;q=0.8,no;q=0.6,nn-no;q=0.5,nn;q=0.4,en-us;q=0.3,en;q=0.1
Connection keep-alive
Host localhost:8888
Referer http://localhost:8888/popup.html
User-Agent Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:17.0) Gecko/20100101 Firefox/17.0
X-Requested-With XMLHttpRequest
Original question:
I'm struggling with what seems to be a common problem, but I've yet to find a solution. I'm trying to execute a very simple jsonp call using jQuery. The problem is that either a) nothing is happening or b), the response from the server is empty.
I've tried several different approaches, using both the $.ajax method and the $.getJSON method. Both produce the same faulty result. Using the code below nothing happens: Using the Chrome debugger I can see that it simply stops its execution halffway trough the method. However using Wireshark I can see that the client performs the three way handshake and thusly prepars to send data, it just fails to do that.
If I remove the callback=? it does execute, however the response is malformed (or at least, I think so since I can only see a response marked with a red line in Firebug).
$.ajax({
url: "http://mydomain.com/asd.php", //"http://localhost:8888/index.php",
dataType: 'jsonp',
type: 'GET',
data: {p:p, u:u, s:symbols, pl:pl, secret:secret},
contentType: "application/json; charset=utf-8",
async: false,
success: function(data){
console.log("What " + data.test);
},
error: function(data){
console.log("failed for some reason");
}
});
Server code ($callback = $_GET["callback"]
<?php header('content-type: application/json; charset=utf-8');
.
.
.
$data = array
(
"message" => $message,
"status" => $statuscode,
"length" => strlen($message)
);
echo $callback . '('.json_encode($data) .')';
exit;
?>
Here is the server response with manually typed input.
funcName({"message":"!0b7(cb6Gv40","status":"OK","length":12})
It is hard to debug this without a jsfiddle/jsbin, so my best suggestion would be to try getting the request to work with fake, static data (just an empty JSON struct, {}, will do).
It seems that the problem might lie in how you are using json_encode, since you write that when you add the callback=? param the response looks mangled. The suggested test will let you diagnose better where the issue lies.
This will obviously NOT work if you did not set up your SSL certificates properly.
This works properly when I transform the https to http: http://jsfiddle.net/eysEe/
var u = "test";
var p = 1234;
var symbols = false;
var pl = 16;
var secret = "c68f39913f901f3ddf44c707357a7d70";
$.ajax({
url: "http://serve.pin2pass.com?index.php",
dataType: 'jsonp',
type: 'GET',
data: {
p: p,
u: u,
s: symbols,
pl: pl,
secret: secret
},
contentType: "application/json; charset=utf-8",
async: false,
success: function(data) {
$('#test').text(data.message);
},
error: function(data) {
$('#test').text("SDf");
}
});
You can tell if you have bad SSL installation when "https://serve.pin2pass.com?index.php" leads to a risky page. Maybe you never intended to put it in https mode ?
callback is the universal GET param for wrapper function name for the jsonp. When you use callback=? in jQuery request, jQuery will parse the ? into something else with a time stamp so it will be always be a unique value. The API server will wrap the json in this unique function name, and jQuery stores the name so it can use it to unwrap the response.
Some API's are not flexible and require their own specific name in which case you can use the jsonpCallback option in either $.ajax or set it globally in $.ajaxSetup
See $.ajax API docs: http://api.jquery.com/jQuery.ajax/
Starting from your code I've set it up locally and everything works as expected:
test.php :
<?php
$callback = $_GET["callback"];
$data = array
(
"message" => 'test',
"status" => 200,
"length" => strlen('test')
);
echo $callback . '('.json_encode($data) .')';
exit;
test.html :
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script>
$(document).ready(function(){
$.getJSON("http://localhost/test.php?callback=?",
{
whatever: 1,},
function(data) {
alert("hmm");
});
});
</script>
</head>
<body>
</body>
</html>
Two things that could help you :
Not putting the callback=? in your call fails because the JSON returned from your server is not valid JSON (due to the parenthesis around your json data). $.getJSON will silently fail in this case. If you want to see the error, use $.ajax instead.
Your problem might come from the fact that you're apparently trying to use https here. In Chrome at least, making an AJAX request to an https URL with an invalid certificate (I assume your localhost or test domain doesn't have a valid certificate) just puts an error in the console. The browser never prompts with the "are you sure?" about the certificate.
Hope it helps
Hm, can you try using 'Fiddler' to debug the call? Perhaps that empty server response isn't that empty after all.
Or maybe your server has some strange security settings, and checks the REFERRER header to block out external calls?
If you can give a full url to your app I could test it for you =)
So, with the new fiddle it was much easier to work. This is a working sample of your call-
var u = "test";
var p = 1234;
var symbols = false;
var pl = 16;
var secret = "c68f39913f901f3ddf44c707357a7d70";
$.ajax({
url: "https://serve.pin2pass.com/index.php",
dataType: 'jsonp',
type: 'GET',
data: {
p: p,
u: u,
s: symbols,
pl: pl,
secret: secret
},
contentType: "application/json; charset=utf-8",
aync:true,
success: function(data) {
$('#test').text(data.message);
},
error: function(data) {
console.log("failed for some reason");
}
});​
jsfiddle
I hope I am not missing something here. The only change I had to do is in the request url, from
https://serve.pin2pass.com?index.php
to
https://serve.pin2pass.com/index.php
Hope this solves it.

POST json data via ajax sends an empty array

I'm trying to post data via ajax, this is my info:
var jsondata =
{"address" : [
{ "id": addid, "streetaddress": streetaddress, "city": city, "state": state, "zipcode": zipcode, "latitude": latitude},
]
};
var jsontosend = JSON.stringify(jsondata, null, 2);
ajax function:
$.ajax({
type: "POST",
url: "process.php",
contentType: "application/json; charset=utf-8",
dataType: "JSON",
data: jsontosend,
success: function(msg){
alert(msg);
}
});
return false;
alert('Data sent');
}
on the php end, when i print_r($_POST) it just says
array(0) {
}
I'm alerting (jsontosend) and its showing me everything perfectly, as well as in firebug using post mothod, its showing all the params sent in a perfect clean manner.
The only way it passes any data is if I use GET method.
Any advice is greatly appreciated!
EDIT: adding POST data from firebug.
this is whats being alerted from the alert function:
{"address":[{"id":1473294,"streetaddress":"3784 Howard Ave","city":"Washington DC","state":"DC","zipcode":20895,"latitude":39.027820587}]}
this is what firebug is showing as whats being passed when using POST method:
myData=%7B%0A++++%22address%22%3A+%5B%0A++++++++%7B%0A++++++++++++%22id%22%3A+76076%2C%0A++++++++++++%22streetaddress%22%3A+%223784+Howard+Ave%22%2C%0A++++++++++++%22city%22%3A+%22Washington+DC%22%2C%0A++++++++++++%22state%22%3A+%22DC%22%2C%0A++++++++++++%22zipcode%22%3A+20895%2C%0A++++++++++++%22latitude%22%3A+39.027820587%0A++++++++%7D%0A++++%5D%0A%7D
and this is the response for var_dump of $_POST:
array(0) {
}
this is a var_dump of $_POST['myData']
NULL
I'm skeptical of the way you're using the contentType property. Try taking out contentType. The default content type is
application/x-www-form-urlencoded (http://api.jquery.com/jQuery.ajax/).
Also, use something like {mydata: jsontosend} for your data property.
$.ajax({
type: "POST",
url: "process.php",
//contentType: "application/json; charset=utf-8",
dataType: "JSON",
data: {mydata: jsontosend},
success: function(msg){
alert(msg);
}
});
Use
data:{myData: jsontosend}
It should send myData as a parameter in your request.
PHP doesn't understand application/json requests (by default).
See this question: How to post JSON to PHP with curl
I found that the comment provided by dkulkarni was the best solution here. It is necessary to read directly from the input stream to get POST data of any complexity. Changing the value of $.ajax({contentType: ''}) did not work for me..
In order to troubleshoot this problem I had set up a controller method to echo back the JSON I was posting to my server. Changing the ContentType header made no difference.
But after reading dkulkarni's comment I changed my server code from this:
return $_POST;
to this:
$data = file_get_contents('php://input');
return json_decode($data);
It worked perfectly.
As dkulkarni commented in his post (Jan 24 at 7:53), the only way to retrieve JSON sent with Content-Type application/json seems to be to retrieve it directly from the input stream.
I made a lot of tests with different approaches, but always when I set Content-Type to JSON, the $_POST in PHP is empty.
My problem is I need to set Content-Type to JSON, because the server (where I don't have access) expects it, otherwise it returns unsupported datatype. I suppose they are retrieving directly from input stream.
Why I have to reproduce that in own PHP file? Because I need to make a proxy for testing issues, but thats not the point of this thread.
Taking contentType out is not a good idea. You DO want to send this data in JSON format. Key is to do what has been mentioned above, instead of trying to access the data on the receiving end (the target php file) with $data= $_POST it is critical to use $data = file_get_contents('php://input');
Here is an example of the entire round trip for a scenario with php and knockout.js:
JS (on requesting page):
function() {
var payload = ko.toJSON({ YOUR KNOCKOUT OBJECT });
jQuery.ajax({
url: 'target.php',
type: "POST",
data: payload,
datatype: "json",
processData: false,
contentType: "application/json; charset=utf-8",
success: function (result) {
alert(result);
}
});
};
And then in target.php (the page receiving the request):
$data = file_get_contents('php://input');
$payload_jsonDecoded = json_decode($data
Try removing ' dataType: "JSON" ' from the ajax request and check.

Receive POST request in PHP from OpenLayers JavaScript

I have problems in receiving POST request in PHP. I'm using JavaScript to send data to a PHP page with POST request. The JavaScript is from OpenLayers.js, and the part that sends the request looks like this:
var postrequest = OpenLayers.Request.POST({
url: "http://localhost/index.php",
data: "success",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
});
In PHP, I'm using this code to see, what I'm getting:
<?php
print_r($_POST);
?>
This is what happens:
index.php receives POST request.
FireBug also informs that POST Parameters contain Success, the one that was sent.
print_r($_POST); in index.php just gives this: array() and doesn't change after the POST request from JavaScript.
So the data is sent and received, but my PHP code doesn't somehow understand it, or I'm not using the right PHP function.
Any suggestions, where to look, and what to try?
I think the "data" property needs to be an object containing key/value pairs.
eg:
var postrequest = OpenLayers.Request.POST({
url: "http://localhost/index.php",
data: {
userName: "myUsername",
password: "myPassword"
},
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
});
If this works when you print_r($_POST) you should see
array("userName" => "myUsername", "password" => "myPassword")
I guess you need include XMLHttpRequest.js library, you can download it from this link
https://github.com/ilinsky/xmlhttprequest

Categories