php multiple curl urls with while loop - php

I am developing a small script and I am bit messed up with using a couple of curl and while loop.
I want to stop processing curl at a point when one of the URL is giving me a information. Note: I have multiple curl requests.
So my concept is,
I have a couple of URLS, which I have to process and get information from. If information is found on a particular URL, it will be giving me a string. If no information is found, it will give me no value. So I have nearly 10 URLs to process approximately. In all cases, any one of the URL will be giving me information, so the remaining urls will be producing no value. Since processing there much URLS, latency is a issue. So suppose in the sample code below, if the url ends with value2.php gives me a result, then I immediately wanted to stop processing the other URLs. Because I already got the result and no point in running other curl. Then finally I have to print the result.
Also I have a condition where none of the URL produce any result and it will be great if someone shows me how to handle that also.
My sample code.
<?php
///functions here
do {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"example[dot]com/value1.php?process=$param");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$combined = curl_exec ($ch);
curl_close ($ch);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"example[dot]com/value2.php?process=$param");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$combined = curl_exec ($ch);
curl_close ($ch);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"example[dot]com/value3.php?process=$param");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$combined = curl_exec ($ch);
curl_close ($ch);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"example[dot]com/value4.php?process=$param");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$combined = curl_exec ($ch);
curl_close ($ch);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"example[dot]com/value5.php?process=$param");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$combined = curl_exec ($ch);
curl_close ($ch);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"example[dot]com/value6.php?process=$param");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$combined = curl_exec ($ch);
curl_close ($ch);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"example[dot]com/value7.php?process=$param");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$combined = curl_exec ($ch);
curl_close ($ch);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"example[dot]com/value8.php?process=$param");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$combined = curl_exec ($ch);
curl_close ($ch);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"example[dot]com/value9.php?process=$param");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$combined = curl_exec ($ch);
curl_close ($ch);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"example[dot]com/value10.php?process=$param");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$combined = curl_exec ($ch);
curl_close ($ch);
} while (strlen($combined) != 0);
echo $combied;
///functions here
?>

Try the following:
<?php
function callCURL($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$combined = curl_exec ($ch);
curl_close ($ch);
return $combined;
}
function getResult($urls) {
$return = array();
foreach ($urls as $url) {
$response = callCURL($url);
if (strlen($response) !== 0) {
$return[] = $response;
break;
}
}
return $return;
}
$urls = array("example.com/value1.php?process=$param", "example.com/value2.php?process=$param", "example.com/value3.php?process=$param")
$result = getResult($urls);

Like you have it in your question and how the other answers have it, the problem is that for each request you have to send it, wait for a response, process the data and only then do you make your subsequent requests. This works fine, but it is highly time-inefficient. Say, for example, each request takes 100 ms to make (which probably not unrealistic). For 10 requests you're looking at 1 second of load time. Instead I would recommend forgetting about trying to stop making requests after you find your result and send all the requests... simultaneously. This can be accomplished with PHP's curl_multi_* functions.
// Put all of your URLs in here. I'm just using google for
// all as an example:
$urls[] = 'http://www.google.com';
$urls[] = 'http://www.google.com';
$urls[] = 'http://www.google.com';
$urls[] = 'http://www.google.com';
$urls[] = 'http://www.google.com';
$urls[] = 'http://www.google.com';
// Get cURL handles
foreach ($urls as $key => $url) {
$chs[$key] = curl_init();
// Set all your options for each connection here
curl_setopt($chs[$key], CURLOPT_URL, $url);
curl_setopt($chs[$key], CURLOPT_HEADER, 0);
}
//create the multiple cURL handle
$mh = curl_multi_init();
//add the handles
foreach ($chs as &$ch) {
curl_multi_add_handle($mh,$ch);
}
$active = null;
//execute the handles
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
foreach ($chs as $url=>&$ch) {
$html = curl_multi_getcontent($ch);
// [do what you want with the HTML]
curl_multi_remove_handle($mh, $ch); // remove the handle (assuming you are done with it);
}
curl_multi_close($mh);

You can use something like this. I didn't check the code, after debug it should work.
function callcurl($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"example[dot]com/value5.php?process=$param");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$ret = curl_exec ($ch);
curl_close ($ch);
}
$urls = array('url1', 'url2'); /// etc
$combined = ''
$cnt = 0;
do {
$combined = callcurl($urls[$cnt++]);
} while (strlen($combined) != 0 && $cnt < count($urls)); //
print $combined;

You can achieve this using a for loop.
$fileNames = array(
'0' => 'valueabc',
'1' => 'valuedef',
[...] => [...]
);
$combined = array();
for ($i = 1; $i < 10; $i++)
{
$ch = curl_init();
$url = "example[dot]com/" . $fileNames[$i] . ".php?process=" . $param;
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$combined[$i] = curl_exec ($ch);
curl_close ($ch);
}
To see all the responses you can foreach $combined.
foreach ($combined as $value=>$response)
{
// TODO: Work with the response
echo "[" . $value . "]" . $response;
}

Related

How to use curl and an array of URLs together

I found this code that does what I'm looking for on a single domain check. But I have a list of URLs that I would like to check.
Can you and how would you create an array with curl?
$url = 'http://www.example.com';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, true); // we want headers
curl_setopt($ch, CURLOPT_NOBODY, true); // we don't need body
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_TIMEOUT,10);
$output = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo 'HTTP code: ' . $httpcode;
If all you want are headers, then instead of curl try:
$urls = array('http://www.example.com','http://www.example.com2','http://www.example.com3','http://www.example4.com');
$httpCodes = [];
foreach($urls as $url)
{
$httpCodes[$url] = get_headers($url)[0];
}
var_dump($httpCodes);
This uses get_headers() to get the header data from a URL's response.
Edit: Or if you really want to use curl. you can use the following code with curl_multi instead:
$urls = array('http://www.example.com','http://www.example.com2','http://www.example.com3','http://www.example4.com');
$curlMultiReq = curl_multi_init();
$ch = [];
foreach($urls as $key => $url)
{
$ch[$key] = curl_init($url);
curl_setopt($ch[$key], CURLOPT_HEADER, true); // we want headers
curl_setopt($ch[$key], CURLOPT_NOBODY, true); // we don't need body
curl_setopt($ch[$key], CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch[$key], CURLOPT_TIMEOUT,10);
curl_multi_add_handle($curlMultiReq, $ch[$key]);
}
$running = '';
do {
curl_multi_exec($curlMultiReq, $running);
curl_multi_select($curlMultiReq);
} while ($running > 0);
foreach(array_keys($ch) as $key){
echo curl_getinfo($ch[$key], CURLINFO_HTTP_CODE);
echo "\n";
curl_multi_remove_handle($curlMultiReq, $ch[$key]);
}
curl_multi_close($curlMultiReq);

VirusTotal API (php) always return 0

I want to use VirusTotal as way that they wrote in their websites.
<?php
$virustotal_api_key = '9491e275f708f55b0777b495411556c916afdda7255d4614500d4aed27175001';
$scan_url = 'https://www.google.com/';
$post = array('apikey' => $virustotal_api_key,'url'=> $scan_url);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://www.virustotal.com/vtapi/v2/url/scan');
curl_setopt($ch, CURLOPT_POST, True);
curl_setopt($ch, CURLOPT_VERBOSE, 1); // remove this if your not debugging
curl_setopt($ch, CURLOPT_RETURNTRANSFER ,True);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$result=curl_exec ($ch);
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
print("status = $status_code\n");
if ($status_code == 200) { // OK
$js = json_decode($result, true);
print_r($js);
} else { // Error occured
print($result);
}
curl_close ($ch);
?>
But I always return error as:
status = 0
I have been searching a lot and still found nothing!!!
I very appreciate if u help me out.
tnx.
I have figured out what was the problem.
This is because thier website banned my country(Iran) IPs.
I wasted my time from morning to noon to found this out :( :(
I should search for something else like this.

PHP curl questions

<?php
ini_set('display_errors',1);
$url = 'www.google.com.my';
$header = true;
$returntransfer = true;
$connecttimeout = 3;
$timeout = 60;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, $returntransfer);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connecttimeout);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
$execute = curl_exec($ch);
$info = curl_getinfo($ch);
header('Content-Type: text/plain');
echo $execute;
echo "\n\ncurl_getinfo() said:\n", str_repeat('-', 31 + strlen($url)), "\n";
foreach ($info as $label => $value)
{
printf("%-30s %s\n", $label, $value);
}
echo str_repeat('-', 31 + strlen($url));
?>
Here is my questions:
(1) I want to test the web services using PHP curl. Am I missing something based from the above code?
(2) If I have 2 URLs, should I use curl_setopt or curl_multi_init?
I really hope that someone will answer my questions.
It's a simultaneous requests:
$ch_1 = curl_init('http://url.one.com/');
$ch_2 = curl_init('http://url.two.com/');
curl_setopt($ch_1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch_2, CURLOPT_RETURNTRANSFER, true);
// build the multi-curl handle, adding both $ch
$mh = curl_multi_init();
curl_multi_add_handle($mh, $ch_1);
curl_multi_add_handle($mh, $ch_2);
// execute all queries simultaneously, and continue when all are complete
$running = null;
do {
curl_multi_exec($mh, $running);
} while ($running);
// all of our requests are done, we can now access the results
$response_1 = curl_multi_getcontent($ch_1);
$response_2 = curl_multi_getcontent($ch_2);
echo "$response_1 $response_2"; // same output as first example

Create a String with a for loop and then use cURL to post

Please help me out how can I make this working if it is th righ way to do it and if it not what would you suggest to post the parameters
$str = '';
for( $i = 11; $i <= 20; $i++ )
{
$str .= $i . ' ';
}
$ch = curl_init(); //http post to another server
curl_setopt($ch, CURLOPT_URL,"http://xxxx");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,"username=$username&password=$password&string=$str");
// receive server response ...
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec ($ch);
print_r($server_output);
curl_close ($ch);
I understand that your code is correct, but you can use the following function as an helper:
<?php
$url = "http://xxxx";
$str = implode(" ", range(11,20));
$data = array("username" => $username, "password" => $password, "string" => $str);
$server_output = processURL($url, $data);
print_r($server_output);
function processURL($url, $data = array()){
$ch=curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$response = curl_exec ($ch);
curl_close ($ch);
return $response;
}
Note that, I do understand that using range is a bit slower than the for loop, but I like it for its readability and cleaner code :)
If you have access to the script you call with curl, try to add:
var_dump($_POST);
and see what is printed.
I just made your code a bit better readable.
But its correct. Should works.
Try to have a look at the php_errors log file and see if it fires something.
<?php
$str = '';
for( $i = 11; $i <= 20; $i++ ) {
$str .= $i . ' ';
}
$ch = curl_init(); //http post to another server
curl_setopt($ch, CURLOPT_URL , 'http://xxxx');
curl_setopt($ch, CURLOPT_POST , 1);
curl_setopt($ch, CURLOPT_POSTFIELDS , 'username=' . $username . '&password=' . $password . '&string=' . $str);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$server_output = curl_exec ($ch);
print_r($server_output);
curl_close($ch);
#Stoic Passing an array in POSTFIELDS determine the Content-type header = multipart. Could alter the response.

Help fixing php/api/curl code please

What I have in place, is a domain availability check, which connects up to an API and outputs "Available: and Unavailable:" from $tmp. Ths below code will only check the availability ONCE.
I would like to check the availability of the domain, multiple times (possibly on a loop?), without having to run restart cURL connection everytime (as it wastes time - 300ms to 1s per query).
I just don't know how I can connect to cURL once and run the loop (doing the check through the API). Help adjusting the code would be very much appreciated! Minimizing the time it takes to output "available/not available" and looping the checks is key.
Thank you.
Current code
<?php
function GetCurlPage ($pageSpec)
{
$ch = curl_init($pageSpec);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
$tmp = curl_exec ($ch);
curl_close ($ch);
$tmp = preg_replace('/(?s)<meta http-equiv="Expires"[^>]*>/i', '', $tmp);
$tmp = explode('<br>', $tmp);
echo $tmp[0];
echo "<br>";
echo $tmp[1];
echo "<br>";
return $tmp;
}
$returnUrl = "http://www.mysite.com.au/check.php";
$url = "https://www.apisite.com.au/availability/check.php?domain=testdomain&suffixes=.com.au";
$output = GetCurlPage("$url");
?>
#Marc B
function getCurlPage($pageSpec) {
if (is_null($ch)) {
$ch = curl_init($pageSpec);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
} else {
curl_setopt($ch, CURLOPT_URL, $pageSpec);
}
while ($i < 5) {
$tmp = curl_exec ($ch);
//curl_close ($ch);
$tmp = preg_replace('/(?s)<meta http-equiv="Expires"[^>]*>/i', '', $tmp);
$tmp = explode('<br>', $tmp);
echo $tmp[0];
echo "<br>";
echo $tmp[1];
echo "<br>";
echo udate('H:i:s:u');
echo "<br><br>";
$i++;
}
return $tmp;
}
This should answer your question: Persistent/keepalive HTTP with the PHP Curl library?
comment followup:
function getCurlPage($pageSpec) {
if (is_null($ch))
static $ch = curl_init($pageSpec);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
} else {
curl_setopt($ch, CURLOPT_URL, $pageSpec);
}
$tmp = curl_exec($ch);
... do NOT close the curl handle, otherwise do the rest the same as before ...
}
Probably won't work as is, doing this off the top of my head and with only 2 hours sleep, but this should be enough to get you started.
And by the way, there's no need to do doublequotes for GetCurlPage("$url"), it's a waste of parser time, as PHP will have to create a new empty string, stuff $url into it, and pass the new string on down. Just do GetCurlPage($url).

Categories