cURL function to retrieve JSON data in PHP - php

I coded this function to retrieve JSON data from an API (which returns data in JSON format).
function file_get_contents_curl($url,$json=false){
$ch = curl_init();
$headers = array();
if($json) {
$headers[] = 'Content-type: application/json';
$headers[] = 'X-HTTP-Method-Override: GET';
}
$options = array(
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER => array($headers),
CURLOPT_TIMEOUT => 5,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HEADER => 0,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_MAXREDIRS => 3,
CURLOPT_USERAGENT => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)'
);
curl_setopt_array($ch,$options);
$response = curl_exec($ch);
curl_close($ch);
if($response === false) {
return false;
} else {
return $response;
}
}
If $response is in fact ===false, does it mean that cURL could not connect to the URL? Or could it also be that the API itself returned nothing (but the connection was successful)?
How do I know if cURL connects properly to the URL?

PHP curl doc says:
Return Values
Returns TRUE on success or FALSE on failure. However, if the
CURLOPT_RETURNTRANSFER option is set, it will return the result on
success, FALSE on failure.
Check error using curl_error

If $response === false then curl failed.
It does not mean that curl succeeded but got no content. Since you've turned on CURLOPT_RETURNTRANSFER, that means the response will be returned as a string. So, no content should be indicated by $response === ''.
Where you would run into trouble is if you only had two equal signs rather than three. With three, you're doing type checking, so the boolean false is not the same as an empty string.

Related

How do I see the output from a PHP file that makes an API call?

I have a PHP file that triggers an API call when a user fills out a form on my site. At the end of the API call, it returns the response.
Where/how can I actually see this response? Filling out the form on the site runs the PHP file, but I'm not sure where it's actually outputting the response at.
Visting /myFile.php doesn't work because it's missing required inputs to actually run the API call.
Any help is much appreciated..
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.sendinblue.com/v3/smtp/email',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>json_encode($payload),
CURLOPT_HTTPHEADER => array(
'api-key: hidden',
'Content-Type: application/json',
'Cookie: __cfduid=dad4a689606c86c195e4d8ce33b53c5c51611684716'
),
));
$response = curl_exec($curl);
curl_close($curl);
return json_decode($response, true);
The Sendinblue documentation says the HTTP status code of the response is 201 or 400.
You can use curl_getinfo() with CURLINFO_HTTP_CODE to get the status.
You can check if the messageId is defined in the response.
You also need to check to cURL errors using curl_error().
$response = curl_exec($curl);
// Check cURL error
if ($response === false) {
$error = curl_error($ch);
die("Error $error"); // for example
}
// decode JSON
$reponseData = json_decode($response, true);
// Check HTTP status
$httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
// Status "Bad request"
if ($httpcode == 400) {
$error = $reponseData['message'];
die("Error $error"); // for example
}
// Status "Created"
if ($httpcode == 201) {
if (! empty($reponseData['messageId'])) {
// Message sent !
}
}

Accept-Language of CURLOPT_HTTPHEADER does not work

cUrl set language header
I was trying to get the source code of Facebook's homepage by using cURL, but it was all Chinese due to the location of my server host. For this reason, I added Accept-Language of CURLOPT_HTTPHEADER to change the language to English, but failed. According to the answer I quoted above, below is the PHP code of cURL I tried:
<?php
$url = "http://www.facebook.com/";
if(isset($_SERVER['HTTP_USER_AGENT']))
$user_agent = $_SERVER['HTTP_USER_AGENT'];
else
$user_agent = "";
$options = array(
CURLOPT_RETURNTRANSFER => true, // return web page
CURLOPT_HEADER => false, // don't return headers
CURLOPT_FOLLOWLOCATION => true, // follow redirects
CURLOPT_HTTPHEADER => array("Accept-Language: en-US;q=0.6,en;q=0.4"),
CURLOPT_USERAGENT => $user_agent);
$ch = curl_init($url);
curl_setopt_array($ch, $options);
$content = curl_exec($ch);
$err = curl_errno($ch);
$errmsg = curl_error($ch);
$header = curl_getinfo($ch);
curl_close($ch);
echo $content;
?>
But it still showed Chinese:
How can I solve this problem?

Having issues with checking whether a URL exists PHP

I have read many question regarding the title. Basically I'm using combination of getheader and curl to check wether a url is exist.
$url = "http://www.asdkkk.com";
$headers = get_headers($url);
if(strpos($headers[0],'404') === false){
$ch = curl_init($url);
curl_setopt_array($ch,array(
CURLOPT_HEADER => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_HTTPHEADER => array("Accept-Language: en-US;q=0.6,en;q=0.4"),
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.6 (KHTML, like Gecko) Chrome/16.0.897.0 Safari/535.6'
));
$data = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($httpCode != 404){
curl_close($ch);
return $data;
}
}else{
echo "URL Not Exists";
}
Both function will return status code 200 for the url("http://www.asdkkk.com"). In the url is a page not found website. But it seem like it is hosted and the header of the page doesn't set to 404. I have try out not only this url but others too. So how can I determine a URL is actually existence in a very accurate way?
I think the issue with your example code is you are confusing a 404 HTTP response code for 'Not Found' from a server with the case of a URL that doesn't point to any server at all. If there's no server response at all, cURL will return '0' as the HTTP response, rather than 404. Try running the below code and see if it works for your purposes:
$urls = array(
"http://www.asdkkk.com",
"http://www.google.com/cantfindthisurl",
"http://www.google.com",
);
$ch = curl_init();
foreach($urls as $url){
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);
$http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
echo "$http_status for $url <br>";
}

curl and ping - how to check whether a website is either up or down?

I want to check whether a website is up or down at a particular instance using PHP. I came to know that curl will fetch the contents of the file but I don't want to read the content of the website. I just want to check the status of the website. Is there any way to check the status of the site? Can we use ping to check the status? It is sufficient for me to get the status signals like (404, 403, etc) from the server. A small snippet of code might help me a lot.
something like this should work
$url = 'yoururl';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_exec($ch);
$retcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if (200==$retcode) {
// All's well
} else {
// not so much
}
curl -Is $url | grep HTTP | cut -d ' ' -f2
curl -Is $url outputs just the headers.
grep HTTP filters to the HTTP response header.
cut -d ' ' -f2 trims the output to the second "word", in this case the status code.
Example:
$ curl -Is google.com | grep HTTP | cut -d ' ' -f2
301
function checkStatus($url) {
$agent = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; pt-pt) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27";
// initializes curl session
$ch = curl_init();
// sets the URL to fetch
curl_setopt($ch, CURLOPT_URL, $url);
// sets the content of the User-Agent header
curl_setopt($ch, CURLOPT_USERAGENT, $agent);
// make sure you only check the header - taken from the answer above
curl_setopt($ch, CURLOPT_NOBODY, true);
// follow "Location: " redirects
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
// return the transfer as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// disable output verbose information
curl_setopt($ch, CURLOPT_VERBOSE, false);
// max number of seconds to allow cURL function to execute
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
// execute
curl_exec($ch);
// get HTTP response code
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpcode >= 200 && $httpcode < 300)
return true;
else
return false;
}
// how to use
//===================
if ($this->checkStatus("http://www.dineshrabara.in"))
echo "Website is up";
else
echo "Website is down";
exit;
Here is how I did it. I set the user agent to minimize the chance of the target banning me and also disabled SSL verification since I know the target:
private static function checkSite( $url ) {
$useragent = $_SERVER['HTTP_USER_AGENT'];
$options = array(
CURLOPT_RETURNTRANSFER => true, // return web page
CURLOPT_HEADER => false, // do not return headers
CURLOPT_FOLLOWLOCATION => true, // follow redirects
CURLOPT_USERAGENT => $useragent, // who am i
CURLOPT_AUTOREFERER => true, // set referer on redirect
CURLOPT_CONNECTTIMEOUT => 2, // timeout on connect (in seconds)
CURLOPT_TIMEOUT => 2, // timeout on response (in seconds)
CURLOPT_MAXREDIRS => 10, // stop after 10 redirects
CURLOPT_SSL_VERIFYPEER => false, // SSL verification not required
CURLOPT_SSL_VERIFYHOST => false, // SSL verification not required
);
$ch = curl_init( $url );
curl_setopt_array( $ch, $options );
curl_exec( $ch );
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return ($httpcode == 200);
}
Have you seen the get_headers() function ? http://it.php.net/manual/en/function.get-headers.php . It seems to do exactly what you need.
If you use curl directly with the -I flag, it will return the HTTP headers (404 etc) instead of the page HTML. In PHP, the equivalent is the curl_setopt($ch, CURLOPT_NOBODY, 1); option.
ping won't do what you're looking for - it will only tell you if the machine is up (and responding to ping). That doesn't necessarily mean that the webserver is up, though.
You might want to try using the http_head method - it'll retrieve the headers that the webserver sends back to you. If the server is sending back headers, then you know it's up and running.
You can not test a webserver with ping, because its a different service. The server may running, but the webserver-daemon may be crashed anyway. So curl is your friend. Just ignore the content.
This function checks whether a URL exists or not. The time of the check is a maximum of 300ms, but you can change that parameter within the cURL option CURLOPT_TIMEOUT_MS
/*
* Check is URL exists
*
* #param $url Some URL
* #param $strict You can add it true to check only HTTP 200 Response code
* or you can add some custom response code like 302, 304 etc.
*
* #return boolean true or false
*/
function is_url_exists($url, $strict = false)
{
if (is_int($strict) && $strict >= 100 && $strict < 600 || is_array($strict)) {
if(is_array($strict)) {
$response = $strict;
} else {
$response = [$strict];
}
} else if ($strict === true || $strict === 1) {
$response = [200];
} else {
$response = [200,202,301,302,303];
}
$ch = curl_init( $url );
$options = [
CURLOPT_NOBODY => true,
CURLOPT_FAILONERROR => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_NOSIGNAL => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_HEADER => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_VERBOSE => false,
CURLOPT_USERAGENT => ( $_SERVER['HTTP_USER_AGENT'] ?? '' ),
CURLOPT_TIMEOUT_MS => 300, // TImeout in miliseconds
CURLOPT_MAXREDIRS => 2,
];
curl_setopt_array($ch, $options);
$return = curl_exec($ch);
$errno = curl_errno($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if (!$errno && $return !== false) {
return ( in_array($httpcode, $response) !== false );
}
return false;
}
You can check any URL, from domain, ip address to images, files, etc. I think this is the fastest way and proven useful.

DOMDocument load on a page returning 400 Bad Request status

I'm trying to use the Last.fm API for an application I'm creating, but am having some problems with validation.
If an API request gives an error it returns a code and message in the response XML like this:
<lfm status="failed">
<error code="6">No user with that name</error>
</lfm>
However, the request also returns an HTTP status of 400 (or in some cases 403) which DOMDocument considers an error and so then refuses to parse the XML.
Is there any way round this, so that I can retrieve the error code and message?
Thanks
Pete
A solution could be to separate your manipulations in two steps :
First, get the XML string, using curl, for example
Then, work on that string with DOMDocument.
There is an example of how you can use curl on the curl_exec manual page ; adding a few useful options, you could use something like this, I suppose :
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "YUR_URL_HERE");
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$xml_string = curl_exec($ch);
curl_close($ch);
// You can now work with $xml_string
And, for more options (there are a lot of them ^^ ), you can take a look to the manual page of curl_setopt.
I resolved the issue by using try & catch. If it can help someone
function getXML($xml) {
$dom = new DomDocument();
try {
#$dom->load($xml); // The '#' is necessary to hide error if it's a error 400 - Bad Request
$root = $dom->documentElement;
return $root;
}
catch(Exception $e)
{
return false;
}
}
You can always get the response with some other function like file_get_contents and then parse the XML with DOMDocument::loadXML
Edit:
http://www.php.net/manual/en/domdocument.load.php#91384
The Function:
function getAlbum($xml,$artist,$album)
{
$base_url = $xml;
$options = array_merge(array(
'user' => 'YOUR_USERNAME',
'artist'=>$artist,
'album'=>$album,
'period' => NULL,
'api_key' => 'xYxOxUxRxxAxPxIxxKxExYxx',
));
$options['method'] = 'album.getinfo';
// Initialize cURL request and set parameters
$ch = curl_init($base_url);
curl_setopt_array($ch, array(
CURLOPT_URL => 'http://ws.audioscrobbler.com/2.0/',
CURLOPT_POST => TRUE,
CURLOPT_POSTFIELDS => $options,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => array( 'Expect:' ) ,
CURLOPT_USERAGENT => 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)'
));
$results = curl_exec($ch);
unset ($options);
return $results;
}
Usage:
// Get the XML
$xml_error = getAlbum($xml,$artist,$album);
// Show XML error
if (preg_match("/error/i", $xml_error)) {
echo " <strong>ERRO:</strong> ".trim(strip_tags($xml_error));
}

Categories