Ajax request fails from FB canvas but works on domain (CodeIgniter) - php

I have the following problem. I have a working PHP/CodeIgniter app and I'm integrating it into Facebook now.
However, an AJAX POST request fails with error 400, and I see in the console that CodeIgniter throws an error saying The URI you submitted has disallowed characters..
This is the URL: https://domain-name.com/apps/main/go_to_game/id=453494284796333&redirect
There are no special characters or anything.
What makes it more confusing:
1) the request works when I open the app on the domain directly (and not through FB)
2) a request to a similar URL works even when sent from FB. This is the URL: https://domain-name.com/apps/main/get_user_stuff/
This is the code that sends the request, pretty basic stuff:
$.post(base+"main/go_to_game/"+gid,function(resp){
//handle response
});
Where base is https://domain-name.com/apps/ and gid is an integer. Any ideas?

Related

Slim3 redirect GET request as POST request

Just started learning Slim3. Have been spending some time figuring out how to perform redirects with overriding original request type with no success.
I want the /origin route to perform the redirect to /dest route.
/origin route receives GET request performs validation and after success redirects with POST request to /dest uri route. Here is the screenshot. I think I am doing something dumb here:
$app->get('/origin', function($req,$res,$args)
{
$req= $req->withHeader('X-Http-Method-Override','POST');
return $res->withRedirect('/dest');
});
$app->post('/dest', function($req,$res,$args)
{
echo "this is destination page";
});
As noted in the comment, this is not possible as the request made by the browser is not in your control.
When you call ->withRedirect() you are sending a status code of 302 and a Location header to the HTTP client (web browser usually).
The web browser sees the 302 status code and then issues a new request to the URL in the Location header. The server has no control over this request and every web browser makes a GET request.
Now, if you want to redirect a POST request to another URL and keep the same POST method, then you can use the 307 status code with a Location header and the browser should do the right thing. Note that this code does not let you change a GET into a POST - it just keeps the same method as the original request for the followup redirection request.

Google drive api file_get_contents and refferer

I am trying to list files from google drive folder.
If I use jquery I can successfully get my results:
var url = "https://www.googleapis.com/drive/v3/files?q='" + FOLDER_ID + "'+in+parents&key=" + API_KEY;
$.ajax({
url: url,
dataType: "jsonp"
}).done(function(response) {
//I get my results successfully
});
However I would like to get this results with php, but when I run this:
$url = 'https://www.googleapis.com/drive/v3/files?q='.$FOLDER_ID.'+in+parents&key='.$API_KEY;
$content = file_get_contents($url);
$response = json_decode($content, true);
echo json_encode($response);
exit;
I get an error:
file_get_contents(...): failed to open stream: HTTP request failed! HTTP/1.0 403 Forbidden
If I run this in browser:
https://www.googleapis.com/drive/v3/files?q={FOLDER_ID}+in+parents&key={API_KEY}
I get:
The request did not specify any referer. Please ensure that the client is sending referer or use the API Console to remove the referer restrictions.
I have set up referrers for my website and localhost in google developers console.
Can someone explain me what is the difference between jquery and php call and why does php call fails?
It's either the headers or the cookies.
When you conduct the request using jQuery, the user agent, IP and extra headers of the user are sent to Google, as well as the user's cookies (which allow the user to stay logged in). When you do it using PHP this data is missing because you, the server, becomes the one who sends the data, not the user, nor the user's browser.
It might be that Google blocks requests with invalid user-agents as a first line of defense, or that you need to be logged in.
Try conducting the same jQuery AJAX request while you're logged out. If it didn't work, you know your problem.
Otherwise, you need to alter the headers. Take a look at this: PHP file_get_contents() and setting request headers. Of course, you'll need to do some trial-and-error to figure out which missing header allows the request to go through.
Regarding the referrer, jQuery works because the referrer header is set as the page you're currently on. When you go to the page directly there's no referrer header. PHP requests made using file_get_contents have no referrer because it doesn't make much sense for them to have any.

Cross Origin $http Requests | Resource

So I was writing an app when I got across this issue.
This is the PHP : Slimframework Corresponding :
$app->delete('/products/:id',function($id) use($app){
$db = new mysqli('notsocoolhost','verycooluser','verycoolpassword','verycooldatabase');
$db->query("DELETE from products WHERE id='$id'");
});
I removed the part where I confirm that you can actually delete it from the database.
This is Angular.JS :
$scope.del = function(product){
$http({
method: "DELETE",
url: baseUrl + product.id
}).success(function(){ ...... //Returns 0 -> WTF?
This buddy here returns in error status : 0
and this one below returns 405:
$scope.delete(baseUrl + product.id).success ... //Returns 405 : Method Not Allowed
To sum it up, I added couple of tests on Hurl.it and the RESTApi from Slimframework is fully functioning. which leaves it as Angular.js problem ? I guess?
UPDATE:
After further inspection I've revealed the following:
1) Mysteriously the : Request Method (Field by Firefox) is OPTIONS.
2) Access-Control-Request-Method : "DELETE"
3) Access-Control-Allow-Methods: "GET,POST,DELETE,PUT"
I hope this serves people in the future.
Back to basics, having trouble sending $http requests in cross-origin requests has nothing to do with the server nor Angular.js.
If you are like me hosting your webapp on:
https:\\www.beautifuldomain.com
and your API on :
https:\\api.beautifuldomain.com
Whenever you try to perform a request between Webapp and API you are performing Cross-Origin Request.
What does it mean?
It means that your message will be considered as Cross-Origin and it will be preflighted.
Preflighted?
It means that when you use any method other than GET,HEAD or POST.
Also POST if used to send request data with Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain, e.g.
It will be sent as method: OPTIONS. -- That is preflighted.
OK, OK I understand, but what do i do?
Now that is clear we have two options to move on:
First Option:
Leaving the web-server structure as is i.e:
www.example.com -> Angular Web-App
api.example.com -> API - subdomain
FOR POST:
And add a transformRequest setting to $httpProvider like so:
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
(Remember preflighted, well it does allow us to send x-www-form-urlencoded.)
What is left from there is make sure you set your data in x-www-form-urlencoded format looks like so :
name=Andy&nickname=RainbowWarrior&....
FOR DELETE:
This one is a bit more complicated since you have to do some server side tweak.
If you are using Slimframework for PHP like I do, all you got to do is:
$response = $app->response();
$response->header('Access-Control-Allow-Origin', '*');
$app->options('/path/to/resource',function(){}); // This one just so you can accept OPTIONS it does nothing.
$app->delete('/path/to/resource',function()
{//your delete code is here
});
Now whenever you try to perform DELETE from angular you will see on XHR tab in w/e browser you are using that There is OPTIONS request that was made and right after DELETE.
Second Option:
Much less of a headache .
Move your API into the same domain i.e
www.example.com - Webapp
www.example.com/api - API
And you are protected from all of that above.
This took me 7 hours of research I hope it will help you guys and save you time!.

Facebook API call works in browser, but not in code

I am working on a Facebook application and I have a script that sends notifications to users whenever an important event has occurred. This script goes through a list of users and fires off notifications in a loop. Now, when I activate the script, nothing happens, and I get the following error in my log concerning the url's that I tried to access:
failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request\r\n
However, when I copy and paste a supposedly bad url into the browser, I get a message of success and the notification appears on Facebook. My question here is, is there any reason the url would not be accepted from a pHP program, but only from browser access?
Here is a code snippet:
$apprequest_url = "https://graph.facebook.com/".
$user_id.
"/notifications?href=apps.facebook.com/vmoodletest".
"&template='sigh'&".
$app_access_token."&method=post";
$result = file_get_contents($apprequest_url);
Here is the resulting url:
https://graph.facebook.com/xxxxxxxxxxxx/notifications?href=apps.facebook.com/vmoodletest&template='blah blah posted a comment on Does it work? in the -General Forum- forum in Senior Project.'&access_token=xxxxxxxxxxxx|xxxxxxxxxxxxxxx&method=post

Cross-domain AJAX request error on HTTP 200

I'm writing a very basic Facebook app, but I'm encountering an issue with cross-domain AJAX requests (using jQuery).
I've written a proxy page to make requests to the graph via cURL that I'm calling via AJAX. I can visit the page in the browser and see it has the correct output, but requesting the page via always causes jQuery to fire the error handler callback.
So I have two files:
Proxy, which does the cURL request
<?php
//Do some cURL requests, manipulate some data
//return it as JSON
print json_encode($data);
?>
The facebook canvas, which contains this AJAX call
$.getJSON("http://myDomain.com/proxy.php?get=stuff",
function(JSON)
{
alert("success");
})
.error(function(err)
{
alert("err");
});
Inspecting the call with Firebug shows it returns with HTTP code 200 OK, but the error handler is always fired, and no content is returned. This happens whether I set Content-Type: application/json or not.
I have written JSON-returning APIs in PHP before using AJAX and never had this trouble.
What could be causing the request to always trigger the error handler?
Recently I experienced the same issue and my problem was the fact that there was a domain difference between the webpage and the API, due to the SSL.
The web page got a HTTP address (http://myDomain.com) and the content I was requesting with JQuery was on the same domain but HTTPS protocol (https://myDomain.com). The browser (Chrome in this case) considered that the domains were differents (the first one with HTTP, the second one with HTTPS), just because of the protocol, and because the request response type was "application/json", the browser did not allowed it.
Basically, the request worked fine, but your browser did not allowed the response content.
I had to add a "Access-Control-Allow-Origin" header to make it work. If you're in the same case, have a look there: https://developer.mozilla.org/en/http_access_control.
I hope that'll help you, I got a headache myself.

Categories