Update: I have solved the problem by using file_get_contents (or other file operations such as fopen) instead of curl, as is shown in this example: https://developers.google.com/chart/image/docs/post_requests. The question is, therefore, why curl is not able to POST the correct parameters while file operations can? This is essentially asking the difference between curl and file_get_contents...
The original problem
I'm using curl in PHP to download an image. The image is a Google Image Chart (https://developers.google.com/chart/image/) generated according to parameters passed through GET or POST to http://chart.googleapis.com/chart. Here is an example chart:
http://chart.googleapis.com/chart?cht=p3&chd=t:60,40&chs=250x100&chl=Hello|World
The simple way is to GET this URL, and it works. However when I tried to GET a longer URL (with more parameters for the data of the chart), Google Chart returned a 400 page saying "malformed or illegal request". I pointed my browser to that longer URL and saw the desired chart, and thus could verify that the parameters in URL were correct.
Suspecting that the problem might be that the URL was too long, I used POST. Here is how I use POST to get the example chart (complete code, you may want to copy it and run):
$postData = array(
'chl' => 'Hello|World',
'chs' => '250x100',
'cht' => 'p3',
'chd' => 't:60,40',
'chof' => 'validate' // turn on the debugging mode
);
$ch = curl_init('http://chart.googleapis.com/chart');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
$ret = curl_exec($ch);
$info = curl_getinfo($ch);
echo $info["request_header"]; // check my sent header
echo $ret; // print out received data, expected: garbled text representing a PNG
curl_close($ch);
Then Google chart returned (even for this example chart) a 400 page saying that "The Chart API request contains no valid parameters." Notice the word "valid" is here, in contrast to "the Chart API request contains no parameters" upon receiving no parameters at all. Therefore Google Chart must have received some parameters but just that it cannot recognize them.
Related
I am calling a Json Array from an API. My doubt is about the way I am getting all the data.
The API has a section to try out the response you should be getting from the API and when I do it I am getting data listed like here
as you can see there are 10 rows going from 0 to 9. But when I am calling the Json array, I am getting this here
as you can see it is all messy.
why is this happening ?? and how can I fix it ?.
I am calling data like this:
$curl = curl_init();
//adding fields to the curl object to enter the site
curl_setopt($curl, CURLOPT_URL, $my_url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_ENCODING, 'gzip,deflate');
//executing the curl call and getting data back
$json = curl_exec($curl);
curl_close($curl); // close the connection
echo $json;
The answer is: it's perception and not a bug per se.
Browsers can be very helpful when it comes to displaying data. When the browser receives a header with the appropriate content type for json (I believe it's application/json) it will try to parse the content as json. This is your first screenshot, when you see the data from the source, where it probably gets the correct headers.
I expect that your php script doesn't set any headers before the code sample you gave us, leaving php itself to decide, what headers to sent. Which means it will usually fallback to "text/html" (because that's what php is historically used for). Now, when your browser receives that header, it will try to parse your json as html, which won't work. Thus it prints it "messy".
Now, to be perfectly clear here: in the first screenshot the 0..9 in every row, this is just a view that your browser offers you, this is not explicitly in the data. the data just says "this is an array, there are these elements in the array". even though the order is significant, but there are no keys for arrays in json!
To "fix" your problem, you have to add the appropriate headers for your content, probably a
header("Content-Type: application/json");
before your code will suffice - at least if i'm not mistaken with the mime type here (but I assume What is the correct JSON content type? holds the right information).
I've been going round in circles trying to get this bit of code working. The problem I am facing is that there could be any number of places where something is wrong and I'm not experienced enough with cURL and API requests to know if I've just done something simple and silly somewhere. The code below is supposed to fetch a JSON response. What I am currently getting is "false". The API developer keeps giving me a CLI sample and I don't know how to "translate" that into something I can use in PHP.
I have to hide the domain, service name and authentication details in my examples.
The string I was given:
'https://[domain]/agw/latest/services/[service]-api/latest/api/v2/[service]-actual-prizes -vk -H "Proxy-Authorization: Basic [authstr]"'
([authstr] is the username and password, separated by a colon and BASE64 encoded - the API dev has confirmed that my authorisation string is correct)
What I have been trying:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://[domain]/agw/latest/services/lottery-api/latest/api/v2/sportka-actual-prizes');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Proxy-Authorization: Basic '.$authstr.'"
,"Content-type: application/json"
));
$response = curl_exec($ch);
curl_close($ch);
var_dump($response);
If I understand this correctly (and I'm not sure that I do), then I'm passing the URL (without flags), saying that I don't want a header in the response (I've tried TRUE as well without any success) and then passing headers with my request that includes the authorisation.
I've tried file_get_contents with a stream_context_create header but that fails too.
Am I missing a header option or flag or something in my cURL code?
I have a cURL request in my code which works fine when running locally:
$url = "http://ipinfo.io/{$_SERVER['REMOTE_ADDR']}";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$response = curl_exec($ch);
$locale = json_decode($response);
and returns a JSON as expected. Our production system is on Google App Engine, however, where I get the website version for a browser rather than the JSON.
I can get this cURL request to work if I change
google_app_engine.enable_curl_lite = "1"
in the php.ini in the root directory of my project to
extension = "curl.so"
but Google's documentation insists the former is to be used on production. Additionally, using the latter breaks things like Monolog's SlackHandler.
Is there a way to get the JSON from this cURL request while still using Google's "cURL Lite"?
From the ipinfo.io documentation:
"We do a little bit of magic on the server to determine if we should send the JSON response or the webpage. We usually get it right, but if you're seeing the webpage instead of the JSON (or want to check the JSON output in a browser) you can force the JSON response by adding /json to the end of the URL"
Adding /json to the end of the URL worked for me in this case, but I wanted a more general solution. Since Google's cURL Lite uses their URL Fetch in the background, ipinfo.io's "magic" is somehow getting confused. I found that by specifying the Accept header then the /json addition wasn't required. In PHP:
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json'));
Thanks to the folks on the #php channel of NashDev Slack for helping me on this one!
I am trying to get data from particular website. Initially I was trying to retrieve data using normal $.ajax() method but because of cross domain problem I drop that idea. Now I'm trying to get same data using PHP's curl function. I'm getting success in it, but I was expecting json response in return but I am getting some kind of json + some other string at the end of that json data. I was even trying to delete that padding with PHP's string operations but I am unable to perform any kind of operations on that data. So, is there any way of doing that? Even when I'm trying to store that $string variable in a log for any text file it is saving the html code not the respose posted below.
Here is my code:
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://www.example.com/do/mapsearch/getResults_ajax");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'city=12&map_type=listing&latlongsearch=1&encrypted_input=UiB8IFFTIHwgUyB8IzIjICB8IG11bWJhaSB8IzMjICB8IE5SSSB8IFkgIzIxI3wgIHwgMSw0LDIsMyw5MCw1LDIyIHwgMTIgfCMxIyAgfCBPLEEsQiMzIyB8IDEsNCwyLDMsOTAsNSwyMiM1IyB8IE8sQSxCICMzMSN8ICA%3D&keyword=&sortby=&mapsearch=1&locality_array=null&building_id=&latitude=19.137212294689522&longitude=72.8479625817871&latlongsearchdistance=3&page=1');
curl_setopt($ch, CURLOPT_POST, 1);
$string = curl_exec($ch);
// it's not even printing these two lines
echo "<br /><br/><br/>";
echo "hie";
echo curl_error($ch);
curl_close($ch);
// tring to get type of response but not printing anything on web page
echo gettype($string);
?>
Here is the part of my response:
{"total":2987,"resultsCount":30,"results":[{"PROP_ID":"K19962871","SPID":19962871,"VERIFIED":"N","PROFILEID":"509882","SHORTLISTED":"N","TYPE_DISP":"Apartment","AREA_UNIT":"Sq.Ft.","AREA":580,"AREA_TYPE":"Super built-up ","LOCALITY_ID":4962,"BUILDING_ID":0,"IS_XID_ATTACHED":0,"PRICE_DISP":"86 Lac","CITY":"Mumbai Andheri-Dahisar","LOCALITY":"Jogeshwari (West)","SOCIETY_NAME":"Off S.v. Road","PROP_NAME":"Off S.V. Road","LISTING":"P","BEDROOM_NUM":1,"LATITUDE":"19.1364893","LONGITUDE":"72.8488709","PROP_INFO":{"class_label":"Dealer","dealer_url":"\/sainath-estate-mumbai-andheri-dahisar-drid-509882","text":"Sainath Estate","link":true,"vcard":false},"BLDNG_INFO":{"name":"Off S.v. Road","link":null,"label":"Society :","cls":"fwn ","lcls":null},"DEFAULT_THUMB":{"url":"http:\/\/static.99acres.com\/images\/mapsearch\/nophoto.jpg","type":"noPhoto"},"MAPPED":"N","AVAILABILITY":"Ready to Move","FURNISH":""}],"encrypted_input":"UiB8IFFTIHwgUyB8IzIjICB8IG11bWJhaSB8IzMjICB8IE5SSSB8IFkgIzIxI3wgIHwgMSw0LDIsMyw5MCw1LDIyIHwgMTIgfCMxIyAgfCBPLEEsQiMzIyB8IDEsNCwyLDMsOTAsNSwyMiM1IyB8IE8sQSxCICMxMiN8ICB8IDEgfCAxOS4xMzcyMTIyOTQ2ODk1MjIgfCA3Mi44NDc5NjI1ODE3ODcxIHwgMyAjMTQjfCAg","list_vlnk":"\/property-in-mumbai-ffid?orig_property_type=1,4,2,3,90,5,22&class=O,A,B&search_type=QS&search_location=NRI&pageid=QS&keyword_orig=mumbai&property_type=1,4,2,3,90,5,22","html2":"
Please any suggestions?
Thank you..
i have a hosted script somewhere that only accept POST request.
example, some.hosted/script.php
how can i setup another simple php that can accept GET request and then POST it to the hosted script.
so that i can put up a link like this: other.site/post2hostedscript.php?postthis=data
and then it POST postthis=data to the hosted script.
tnx
edit:
post2hostedscript.php do not give any result.
the result will go directly to some.hosted/script.php
just as if the user POST directly at the hosted script.
Your post2hostedscript.php will have to :
Fetch all parameters received as GET
Construct a POST query
Send it
And, probably, return the result of that POST request.
This can probably be done using curl, for instance ; something like this should get you started :
$queryString = $_SERVER['QUERY_STRING'];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://www.othersite.com/post2hostedscript.php");
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $queryString);
curl_exec($ch);
curl_close($ch);
For a list of options that can be used with curl, you can take a look at the page of curl_setopt.
Here, you'll have to use, at least :
CURLOPT_POST : as you want to send a POST request, and not a GET
CURLOPT_RETURNTRANSFER : depending on whether you want curl_exec to return the result of the request, or to just output it.
CURLOPT_POSTFIELDS : The data that will be posted -- i.e. what you have in the query string of your incoming request.
And note that the response from the POST request might include some interesting HTTP header -- if needed, you'll have to fetch them (see the CURLOPT_HEADER option), and re-send the interesting ones in your own response (see the header function).
Take a look at the "curl" functions, they provide everything you need.
You might consider replacing all instances of $_POST in the old script to $_REQUEST, which will result in it accepting both GET and POST alike.