How to obtain curl exec response - php

I am developing a PHP script that:
Gets 10 rows from DB (works well)
Sends addresses from these rows to Map API
Obtains data
Save results in DB (works well)
I don't know how to obtain the final response of curl_exec. curl_exec
in $response = call('GET', $query);
- even when hasn't completed returns something in response.
These my loop that is waiting for the response of the call function. But it doesn't work json_decode($stringJSON) is invoked earlier than it is obtained the final response
$requestHandled = false;
$response = "";
$response = call('GET', $query);
while(!$requestHandled) {
if(strlen($response) > 5){
$response = mb_convert_encoding($response, "UTF-8");
$stringJSON = get_magic_quotes_gpc() ? stripslashes($response) : $response;
echo $stringJSON;
$jsonObject = "+";
echo $jsonObject;
$jsonObject = json_decode($stringJSON);
echo $jsonObject;
$requestHandled = true;
}
}
This is my curl call function
function call($method, $url, $data = false) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_URL, $url);
if ($data) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$headers = array();
$headers[] = 'Content-Type: application/json';
$headers[] = 'Content-Length: ' . strlen($data);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
return curl_exec($ch);
Please help. Has spent a half of the day solving it

So the result of the var_dump( $response ) is an empty string?
In that case, it simply means the response from the server is empty, because I just tested your function call() and it seems to work just fine. In other words, make sure the URL (with the method GET) you are trying to call actually returns data to begin with.
I wouldn't be surprised if you simply have a typographical error somewhere in the URL.
Also, for debugging purposes, temporarily replace
return curl_exec($ch);
with
$result = curl_exec($ch);
var_dump(curl_getinfo($ch));
return $result;
and investigate the info in the var_dump() result, to make sure the response code is 200 (or any other that indicates success) and not in the 4xx or 5xx ranges (respectively indicating either a client or server error), for instance.
See curl_getinfo() for more information about what useful information will be returned about your last curl transfer.
To address OPs comment(s):
Please try this complete script (nothing else: no while loop, no stripslashes(), no json_decode(), etc):
<?php
function call($method, $url, $data = false) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_URL, $url);
if ($data) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$headers = array();
$headers[] = 'Content-Type: application/json';
$headers[] = 'Content-Length: ' . strlen($data);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
var_dump(curl_getinfo($ch)); // check this result and make sure the response code is 200
return $result;
}
$query = 'fill in the correct URL! (with http(s)://)';
$response = call('GET', $query);
var_dump( $response ); // check this result and see if it's an empty string
die;
If the var_dump( $response ); returns an empty string, it means your script works fine but the URL you are calling simply returned an empty response.
If $response is not empty and actually contains JSON data, replace
var_dump( $response );
with
$stringJSON = mb_convert_encoding( $response, "UTF-8" );
echo $stringJSON; // make sure this contains valid JSON data
// stripslashes() should not be needed
var_dump( json_decode( $stringJSON ) ); // if JSON data was valid, you should get a valid PHP data structure

Related

How to return an object and not a string with PHP curl request

I am attempting to request data from a url and am having success for most endpoints except for one. Throughout my troubleshooting, I can retrieve the text and display it in the browser, however, when I try to store it as an object, I get nothing. It actually still stores as a string. I would like to iterate through the object so that I can run calculations on the contents.
Is it because the JSON string is malformed? If so, how do I correct? I have tried a variety of solutions with no success.
Important to note that gzip is required, for that reason I have included 'ob_gzhandler'. the contents only echos when I use gzhandler.
THE ECHOS IN THE FUNCTION ARE FOR TROUBLESHOOTING PURPOSES. THEY ILLUSTRATE WHERE STRINGS ARE BEING PRODUCED AND NOT OBJECTS.
function CallAPI_oanda_v20($instruments)
{
$curl = curl_init();
$url = 'https://api-fxtrade.oanda.com/v3/instruments/'.$instruments.'/positionBook';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HTTPGET,TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Authorization: <USE MY API KEY>'));
$response = curl_exec($ch);
echo gettype($response); //returns "string"
$json = json_decode($response, true);
echo gettype($json); //returns "NULL"
curl_close($ch);
return $json;
}
$call = CallAPI_oanda_v20("GBP_USD");
ob_start('ob_gzhandler');
//$output = ob_get_contents();
echo $call->positionBook; //returns an error:Trying to get property 'positionBook' of non-object
echo gettype($output); //THIS WILL RETURN "string".
$jsonIterator = new RecursiveIteratorIterator(
new RecursiveArrayIterator(json_decode($output, TRUE)),
RecursiveIteratorIterator::SELF_FIRST);
foreach ($jsonIterator as $key => $val) {
if(is_array($val)) {
echo "$key:\n";
} else {
echo "$key => $val\n";
}
}
In order to troubleshoot that the call is correct, I echo the contents by graying out the following line:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
Here is the json string that prints:
{"positionBook":{"instrument":"GBP_USD","time":"2019-09-02T00:00:00Z","unixTime":"1567382400","price":"1.21584","bucketWidth":"0.00050","buckets":[{"price":"1.19950","longCountPercent":"0.0189","shortCountPercent":"0.0189"},{"price":"1.20000","longCountPercent":"0.0000","shortCountPercent":"0.0189"},{"price":"1.20100","longCountPercent":"0.0000","shortCountPercent":"0.0189"},{"price":"1.20150","longCountPercent":"0.0000","shortCountPercent":"0.0757"}]}}
ob_start('ob_gzhandler');
$output = ob_get_contents();
echo gettype($output); //THIS WILL RETURN "string".
This is exactly what you expect. The output buffer is just a big string that is appended to whenever you write to it. When you gettype($output) you're just getting the output of that buffer, which is nothing to do with any of your other code.
As you're not actually writing anything to said buffer, it will be an empty string.
You're not actually using the result of your function ($call) anywhere. You should be passing it to your recursive array iterator. In your top function you probably want to add TRUE as the second argument to json_decode so it's fully array based.
SOLVED. I was improperly decoding the gzip string.
$response = gzdecode($response);
This was the key, along with removing:
ob_start('ob_gzhandler');
$output = ob_get_contents();
Here is the solved piece of code:
{
$curl = curl_init();
$url = 'https://api-fxtrade.oanda.com/v3/instruments/'.$instruments.'/positionBook';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HTTPGET,TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Authorization: <USE MY API KEY>'));
$response = curl_exec($ch);
$response = gzdecode($response);
$json = json_decode($response, true);
curl_close($ch);
return $json;
}
$call = CallAPI_oanda_v20("GBP_USD");
echo '<pre>';
print_r($call);
echo '<pre>';```

Issue sending headers to Rest API

I have to write to an API, and nothing seems to work. When I use apitester.com it works though. When I use my app, it doesn't. I output the headers and payload and they look the same between the two, so I am assuming I'm doing something wrong. Here is my PHP to send data to the API
<?php
$email = $_POST['email'];
$expired = NULL;
$funded = TRUE;
$data = array(
"email" => $email,
"expired" => $expired,
"funded" => $funded
);
$url = 'https://my.rest.api';
$json_string = json_encode($data);
$headers = array (
"Content-Type: application/json",
"Authorization: Bearer xxx"
);
$channel = curl_init($url);
curl_setopt($channel, CURLOPT_RETURNTRANSFER, true);
curl_setopt($channel, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($channel, CURLOPT_HTTPHEADER, $headers);
curl_setopt($channel, CURLOPT_POSTFIELDS, $json_string);
curl_setopt($channel, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($channel, CURLOPT_CONNECTTIMEOUT, 10);
$statusCode = curl_getInfo($channel, CURLINFO_HTTP_CODE);
curl_exec($channel);
http_response_code($statusCode);
if ( $statusCode != 200 ){
echo "Data submitted was ".$json_string." Returned status code: {$statusCode} \n".curl_error($channel);
} else {
echo $response;
}
//I turn the below 2 lines on and off to see what I am actually sending
// print_r($headers);
// echo $json_string;
curl_close($channel);
?>
I get the returned status code of "0" on my app, but "200" using the tester. Is there something obviously wrong with the curl options I am sending?
If you got status 0, it means that the HTTP request didn't complete at all. You can use the following functions to find out what error happened:
curl_errno
curl_errstr
Sidesnotes:
You're echoing $response, but that variable doesn't exist.
Using CURLOPT_SSL_VERIFYPEER is a really bad idea. Make sure you remove it before you go to production.

Wunderlist Tasks - how do I get the tasks for a list using curl in php

I have been searching quite a bit now and can't get an overview of Tasks from a single list using the Wunderlist endpoint: https://a.wunderlist.com/api/v1/tasks
I can get Lists, Folders and create List, Folders, Tasks so that works fine. But how do I get the Tasks from a list? I tried to interpret the documentation found here: https://developer.wunderlist.com/documentation/endpoints/task
When I do a GET method I get this error message:
{"error":{"type":"missing_parameter","translation_key":"api_error_missing_params","message":"Missing parameter.","title":["required"]}}
However, I don't want to add a title, since I don't want to create a new task, I just want the tasks of that list back.
What am I doing wrong here?
Here is my code so far:
function doCall($endPoint, $parameters = array(), $method = 'GET')
{
// check if curl is available
if (!function_exists('curl_init')) {
print "This method requires cURL (http://php.net/curl), it seems like the extension isn't installed. ".__LINE__;
exit();
}
//prepare content
$parametersdata = json_encode($parameters);
// define url
$url = 'https://a.wunderlist.com/api/v1/' . $endPoint;
// init curl
$curl = curl_init();
// set options
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 10);
// init headers
$headers = array();
// add to header
$headers[] = 'X-Access-Token: XXX';
$headers[] = 'X-Client-ID: XXX';
// method is POST, used for login or inserts
if ($method == 'POST') {
// define post method
curl_setopt($curl, CURLOPT_POST, 1);
// method is DELETE
} elseif ($method == 'DELETE') {
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');
} else {
curl_setopt($curl, CURLOPT_HTTPGET, 1);
}
// parameters are set
if (!empty($parameters)) {
$headers[] = 'Content-Type: application/json';
$headers[] = 'Content-Length: ' . strlen($parametersdata);
curl_setopt($curl, CURLOPT_POSTFIELDS, $parametersdata );
}
// define headers with the request
if (!empty($headers)) {
// add headers
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
}
// execute
$response = curl_exec($curl);
// debug is on
if (true) {
echo $method." ".$url . '<br/><pre>';
print"\n--headers--\n";
print_r($headers);
print"\n--parameters--\n";
print_r($parameters);
print"\n--parametersdata--\n";
print_r($parametersdata);
print"\n--response--\n";
print_r($response);
echo '</pre><br/><br/>';
}
// get HTTP response code
$httpCode = (int) curl_getinfo($curl, CURLINFO_HTTP_CODE);
// close
curl_close($curl);
// response is empty or false
if (empty($response)) {
//throw new Exception('Error: ' . $response);
print "Error: ". $response." ".__LINE__;
}
// init result
$result = false;
// successfull response
if (($httpCode == 200) || ($httpCode == 201)) {
$result = json_decode($response, true);
}
// return
return $result;
}
$listid = 123;
$url = 'tasks';
$tasks = doCall($url,array('list_id' => $listid), 'GET');
echo $tasks;
-- EDIT ADDENDUM ---
I have also tried these variants in case anyone wonders. They all give the same error "bad_request"
GET a.wunderlist.com/api/v1/tasks{"list_id":"141329591"}
GET a.wunderlist.com/api/v1/tasks{"list_id":141329591}
GET a.wunderlist.com/api/v1/tasks/{"list_id":"141329591"}
As pointed out by Rotem, you're using adding the $parameters array as CURLOPT_POSTFIELDS. As the name suggests this is meant for http POST requests only.
Putting the parameters as query params in the $url and passing null for the query params made your example work for me.
$listid = 123;
$url = 'tasks?list_id=123';
$tasks = doCall($url,null,'GET');
echo $tasks;
Note: I did use a list_id I have access to instead of using 123

Is it possible to get partial response using PHP cURL?

Here is my code
$url = "partial_response.php";
$sac_curl = curl_init();
curl_setopt($sac_curl, CURLOPT_HTTPGET, true);
curl_setopt($sac_curl, CURLOPT_URL, $url);
curl_setopt($sac_curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($sac_curl, CURLOPT_HEADER, false);
curl_setopt($sac_curl, CURLOPT_TIMEOUT, 11);
$resp = curl_exec($sac_curl);
curl_close($sac_curl);
echo $resp;
Partial_response.php
header( 'Content-type: text/html; charset=utf-8' );
echo 'Job waiting ...<br />';
for( $i = 0 ; $i < 10 ; $i++ )
{
echo $i . '<br/>';
flush();
ob_flush();
sleep(1);
}
echo 'End ...<br/>';
From the about code am trying to get a partial response from partial_response.php. what I want is, I need curl to return me "Job waiting.." alone instead of waiting for the partial_response.php to complete the loop and return the entire data. so when I reduce CURLOPT_TIMEOUT below 11 i dont get any response at all. Kindly clarify my doubt.
Thanks in advance.
I later realized that cURL could not do what I want, I used stream_context_get_options
to achieve what I wanted. Here it is, http://www.php.net/manual/en/function.stream-context-get-options.php.
No, I'm afraid not. At least not that I know of any, this is simply because PHP is a synchronous language, meaning you cannot "skip" tasks. (I.e. curl_exec() will always - no matter what - be executed until the request is completed)
I'm not sure abut the timeout, but you can get partial response using cURL by using the CURLOPT_WRITEFUNCTION flag:
curl_setopt($ch, CURLOPT_WRITEFUNCTION, $callback);
Where $ch is the Curl handler, and $callback is the callback function name. This command will stream response data from remote site. The callback function can look something like:
$result = '';
$callback = function ($ch, $str) {
global $result;
//$str has the chunks of data streamed back.
$result .= $str;
// here you can mess with the stream data either with $result or $str.
// i.e. look for the "Job waiting" string and terminate the response.
return strlen($str);//don't touch this
};
If not interrupted at the end $result will contain all the response from remote site.
So combining everything will look something like:
$result = '';
$callback = function ($ch, $str) {
global $result;
//$str has the chunks of data streamed back.
$result .= $str;
// here you can mess with the stream data either with $result or $str.
// i.e. look for the "Job waiting" string and terminate the response.
return strlen($str);//don't touch this
};
$url = "partial_response.php";
$sac_curl = curl_init();
curl_setopt($sac_curl, CURLOPT_HTTPGET, true);
curl_setopt($sac_curl, CURLOPT_URL, $url);
curl_setopt($sac_curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($sac_curl, CURLOPT_HEADER, false);
curl_setopt($sac_curl, CURLOPT_TIMEOUT, 11);
curl_setopt($ch, CURLOPT_WRITEFUNCTION, $callback);
curl_exec($sac_curl); // the response is now in $result.
curl_close($sac_curl);
echo $result;

php curl help with google url shortner api

Im trying to shorten a url using ggole api's.Here is my php code .It gives a blank page when i load
<?php
define('GOOGLE_API_KEY', 'GoogleApiKey');
define('GOOGLE_ENDPOINT', 'https://www.googleapis.com/urlshortener/v1');
function shortenUrl($longUrl)
{
// initialize the cURL connection
$ch = curl_init(
sprintf('%s/url?key=%s', GOOGLE_ENDPOINT, GOOGLE_API_KEY)
);
// tell cURL to return the data rather than outputting it
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// create the data to be encoded into JSON
$requestData = array(
'longUrl' => $longUrl
);
// change the request type to POST
curl_setopt($ch, CURLOPT_POST, true);
// set the form content type for JSON data
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json'));
// set the post body to encoded JSON data
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($requestData));
// perform the request
$result = curl_exec($ch);
curl_close($ch);
// decode and return the JSON response
return json_decode($result, true);
}
if (isset($_POST['url'])) {
$url = $_POST['url'];
$response = shortenUrl('$url');
echo sprintf(
$response['longUrl'],
$response['id']
);
}
?>
My html file:
<html>
<head>
<title>A BASIC HTML FORM</title>
</head>
<body>
<FORM NAME ="form1" METHOD =" " ACTION = "shortner.php">
<INPUT TYPE = "TEXT" VALUE ="Enter a url to shorten" name="url">
<INPUT TYPE = "Submit" Name = "Submit1" VALUE = "Shorten">
</FORM>
</body>
</html
I think I have found a solution to your problem. Since you are connecting to a URL that uses SSL, you will need to add some extra parameters to your code for CURL. Try the following instead:
<?php
define('GOOGLE_API_KEY', 'GoogleApiKey');
define('GOOGLE_ENDPOINT', 'https://www.googleapis.com/urlshortener/v1');
function shortenUrl($longUrl)
{
// initialize the cURL connection
$ch = curl_init(
sprintf('%s/url?key=%s', GOOGLE_ENDPOINT, GOOGLE_API_KEY)
);
// tell cURL to return the data rather than outputting it
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// create the data to be encoded into JSON
$requestData = array(
'longUrl' => $longUrl
);
// change the request type to POST
curl_setopt($ch, CURLOPT_POST, true);
// set the form content type for JSON data
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json'));
// set the post body to encoded JSON data
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($requestData));
// extra parameters for working with SSL URL's; eypeon (stackoverflow)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
// perform the request
$result = curl_exec($ch);
curl_close($ch);
// decode and return the JSON response
return json_decode($result, true);
}
if (isset($_POST['url'])) {
$url = $_POST['url'];
$response = shortenUrl('$url');
echo sprintf(
$response['longUrl'],
$response['id']
);
}
?>
I think it's coming form your html. You didn't put the form methode, so it send data by get.
And you show something only if you have post.
Try to do in the form method="post"
Edit
Bobby the main problem is that you don't have one problem but several in this code.
First if you don't do
<FORM NAME="form1" METHOD="POST" ACTION="shortner.php">
the if (isset($_POST['url'])) will never return true, because the variable send by the form will be GET (or do a if (isset($_GET['url']))).
Secondly you call the function with { $response = shortenUrl('$url'); }. Here you're not sending the url value but the string '$url'. So your variable $longUrl is always '$url'.
Thirdly you don't use sprintf like you should.
echo sprintf(
$response['longUrl'],
$response['id']
);
Sprintf need to take a string format:
echo sprintf("%s %s" // for example
$response['longUrl'],
$response['id']
);
But do you know that you can do directly
echo $response['longUrl'] . ' ' . $response['id'];
You can concatenate string directly with . in php
curl_exec() returns boolean false if something didn't go right with the request. You're not testing for that and assuming it worked. Change your code to:
$result = curl_exec($ch);
if ($result === FALSE) {
die("Curl error: " . curl_error($ch);
}
As well, you need to specify CURLOPT_RETURNTRANSFER - by default curl will write anything it receives to the PHP output. With this option set, it'll return the transfer to your $result variable, instead of writing it out.
You need to set CURLOPT_RETURNTRANSFER option in your code
function shortenUrl($longUrl)
{
// initialize the cURL connection
$ch = curl_init(
sprintf('%s/url?key=%s', GOOGLE_ENDPOINT, GOOGLE_API_KEY)
);
// tell cURL to return the data rather than outputting it
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// create the data to be encoded into JSON
$requestData = array(
'longUrl' => $longUrl
);
// change the request type to POST
curl_setopt($ch, CURLOPT_POST, true);
// set the form content type for JSON data
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json'));
// set the post body to encoded JSON data
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($requestData));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
// perform the request
$result = curl_exec($ch);
curl_close($ch);
// decode and return the JSON response
return json_decode($result, true);
}
if (isset($_POST['url'])) {
$url = $_POST['url'];
$response = shortenUrl('$url');
echo sprintf(
$response['longUrl'],
$response['id']
);
}
// Create cURL
$apiURL = https://www.googleapis.com/urlshortener/v1/url?key=gfskdgsd
$ch = curl_init();
// If we're shortening a URL...
if($shorten) {
curl_setopt($ch,CURLOPT_URL,$apiURL);
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,json_encode(array("longUrl"=>$url)));
curl_setopt($ch,CURLOPT_HTTPHEADER,array("Content-Type: application/json"));
}
else {
curl_setopt($ch,CURLOPT_URL,$this->apiURL.'&shortUrl='.$url);
}
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
// Execute the post
$result = curl_exec($ch);
// Close the connection
curl_close($ch);
// Return the result
return json_decode($result,true);

Categories