Weird curl+php behaviour - php

My code is pretty simple.
function x($url, $request)
{
static $curl = null;
if (is_null($curl)) $curl = curl_init($url);
$options = array(CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => array('Content-type: application/json'), CURLOPT_POST => true, CURLOPT_POSTFIELDS => $request);
curl_setopt_array($curl, $options);
$response = curl_exec($curl);
echo curl_getinfo($curl)['total_time'].' ';
}
for ($i=0; $i<10000; $i++) x('http://server/', '<...post vars...>');
The problem is that most of the time I get response from the server in 0.0001 sec., but sometimes it is 1.0001 or 2.0001 sec.
The code above may output something like:
0.000632 0.00034 2.001671 0.000526 0.000501 0.000914 0.007355 0.000769 0.001429 0.001249 0.000554 0.001623 0.000595 0.006834 0.000793 0.000436 0.000408 0.006953 0.000867 0.000593 0.000546 0.007408 0.000837 0.001208 0.000652 0.000947 0.000614 0.000641 0.000647 0.001288 0.000501 0.000582 0.000625 0.000288 0.000351 0.000557 0.000601 0.000259 0.000309 0.000541 0.000565 0.000582 0.000949 0.000403 0.000896 0.000487 0.000569 0.001233 1.002649 .0.001107
The problem is not with the server, because there is no such delays if I use for example stream_context_create()+fopen(). It seems like the problem in curl itself, but I can't figure out why is it sleeping sometimes for a second or two.
If I use curl_close and reinitialise $curl each time there is no difference - it still hangs sometimes with the same frequency.
Thank you in advance for your reply.

Related

http post in loop is running timing out

I am trying to send curl request from source to destination in loop. Loop runs for 2 times. First request lasts for 32 seconds and second one for 50 seconds. Finally times out. Controlling timeout is not in my control as it is shared hosting.
Source section below is being run in the browser. the below error message shows after using up 120 seconds
Error Details: Fatal error: Maximum execution time of 120 seconds
exceeded
Question
I am assuming that the request should not timeout, since both requests are submitted separately through their own curl request. Still, it seems like it is getting consolidated to form total one request.
In case I run the loop for one time, then everything works as it takes 30 seconds.
Am I missing anything?
Source
for($i = 0; $i <= 200; $i+= 100) {
$postData = array(
'start' => $i,
'end' => $i + 100
);
$ch = curl_init('Server url');
curl_setopt_array($ch, array(
CURLOPT_POST => TRUE,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json'
),
CURLOPT_POSTFIELDS => json_encode($postData)
));
$response = curl_exec($ch);
$responseData = json_decode($response, TRUE);
curl_close($ch);
echo $response;
}
Destination
public function methodname()
{
$json = json_decode(file_get_contents('php://input'), true);
// .
// .
// Logic that runs for 32 seconds
// .
// .
header('Content-type: application/json');
echo json_encode("message");
}
Try to add a sleep(1) function inner your loop. It could be that the server which you are requested dont like multiple POST request in a short time.
try using cURl's CURLOPT_TIMEOUT or similar configurations. More information https://www.php.net/manual/en/function.curl-setopt.php here
Answer: read the documentation
LE:
You could also use set_time_limit(0); // or value > 120 to increase your script execution timeout

Calling a PHP file from a PHP loop in background

I have a PHP loop where i need to call another PHP file in the background to insert/update some information based on a variable send to it. I have tried to use CURL, but it does not seem to work.
I need it to call SQLupdate.php?symbol=$symbol - Is there another way of calling that PHP with the paramter in the background - and can it eventually be done Synchronously with a response back for each loop?
while(($row=mysqli_fetch_array($res)) and ($counter < $max))
{
$ch = curl_init();
$curlConfig = array(
CURLOPT_URL => "SQLinsert.php",
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => array(
'symbol' => $symbol,
)
);
curl_setopt_array($ch, $curlConfig);
$result = curl_exec($ch);
curl_close($ch);
}
I'm going to weigh in down here in hopes of getting this one "away & done".
Although it isn't entirely clear from your post, it seems you're trying to call your PHP file via an HTTP(s) protocol.
In many configurations of PHP, you could do this and avoid some potential cURL overhead by using file_get_contents() instead:
while(($row=mysqli_fetch_array($res)) and ($counter < $max)) {
$postdata = http_build_query(
array(
'symbol' => $row['symbol']
)
);
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => $postdata
)
);
$context = stream_context_create($opts);
$result = file_get_contents('http://example.com/SQLinsert.php', false, $context);
$counter++; // you didn't mention this, but you don't want a everloop...
}
That's pretty much a textbook example copied from the manual, actually.
To use cURL instead, as you tried to do originally, and in truth it seems pretty clean with one call to curl_setopt() inside the loop:
$ch = curl_init();
$curlConfig = array(
CURLOPT_URL => "http://example.com/SQLinsert.php",
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true
);
curl_setopt_array($ch, $curlConfig);
while(($row=mysqli_fetch_array($res)) and ($counter < $max)) {
curl_setopt($ch, CURLOPT_POSTFIELDS, array('symbol' => $row['symbol']));
$result = curl_exec($ch);
$counter++; //see above
}
// do this *after* the loop
curl_close($ch);
Now the actual and original problem may be that $symbol isn't initialized; at least, it isn't in the example you have provided. I've attempted to fix this by using $row['symbol'] in both my examples. If this isn't the name of the column in the database then you would obviously need to use the correct name.
Finally, be advised that it's almost always better to access a secondary resource via the fastest available mechanism; if "SQLinsert.php" is local to the calling script, using HTTP(s) is going to be terribly under-performant, and you should rewrite both pieces of the system to work from a local (e.g. 'disk-based') point-of-view (which has already been recommended by a plethora of commenters):
//SQLinsert.php
function myInsert($symbol) {
// you've not given us any DB schema information ...
global $db; //hack, *cough*
$sql = "insert into `myTable` (symbol) values('$symbol')";
$res = $this->db->query($sql);
if ($res) return true;
return false;
}
//script.php
require_once("SQLinsert.php");
while(($row=mysqli_fetch_array($res)) and ($counter < $max)) {
$ins = myInsert($row['symbol']);
if ($ins) { // let's only count *good* inserts, which is possible
// because we've written 'myInsert' to return a boolean
$counter++;
}
}

How to fix cURL error "SSL connection timeout" only on the first time the script is called?

I'm facing a strange problem using cURL with PHP on a Windows server. I have a very basic code:
private function curlConnection($method, $url, $timeout, $charset, array $data = null)
{
if (strtoupper($method) === 'POST') {
$postFields = ($data ? http_build_query($data, '', '&') : "");
$contentLength = "Content-length: " . strlen($postFields);
$methodOptions = array(
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postFields,
);
} else {
$contentLength = null;
$methodOptions = array(
CURLOPT_HTTPGET => true
);
}
$options = array(
CURLOPT_HTTPHEADER => array(
"Content-Type: application/x-www-form-urlencoded; charset=" . $charset,
$contentLength,
'lib-description: php:' . PagSeguroLibrary::getVersion(),
'language-engine-description: php:' . PagSeguroLibrary::getPHPVersion()
),
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_CONNECTTIMEOUT => $timeout
);
$options = ($options + $methodOptions);
$curl = curl_init();
curl_setopt_array($curl, $options);
$resp = curl_exec($curl);
$info = curl_getinfo($curl);
$error = curl_errno($curl);
$errorMessage = curl_error($curl);
curl_close($curl);
$this->setStatus((int) $info['http_code']);
$this->setResponse((String) $resp);
if ($error) {
throw new Exception("CURL can't connect: $errorMessage");
} else {
return true;
}
}
The problem is that the first time this script is called, the response is always this: string(22) "SSL connection timeout".
Subsequent calls to the script output the desired result, but, if I wait a couple of minutes before calling the script again, the timeout issue happens again.
So, steps to reproduce the "error":
Call the script -> SSL connection timeout
Call the script again -> works fine
Call the script one more time -> works fine
Call the script n more times -> works fine
Wait 10 minutes
Call the script -> SSL connection timeout
Call the script n more times again -> works fine
If I call any other script the response is immediate, even after a period of inactivity, so this behaviour only happen when cURL is involved.
PHP - 5.2.17
CURL - libcurl/7.16.0 OpenSSL/0.9.8q zlib/1.2.3
The server is running Windows 2012 with IIS 8, latest upgrades, running PHP on FastCGI.
Does anyone have any idea on how I can solve this?
Thanks.
Try using the ca-bundle.crt bundle available here https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt
Upload file
curl_setopt($ch, CURLOPT_CAINFO, "path");
Reference: http://richardwarrender.com/2007/05/the-secret-to-curl-in-php-on-windows
Hope this helps.
Try to check the state of the 'Server' Windows service, if stopped - could be the reason. Have no idea how it is related, but it helped for me with the same issue.

curl_exec() prints the returned JSON data, won't put it into a variable

There are many such questions on Stack Overflow & elsewhere, but they all seem to be for earlier versions of PHP as their answers refer to CURLOPT_RETURNTRANSFER, open_basedir and allow_url_include.
I am using PHP 5.4.17. Here’s my code:
$curl = curl_init();
if ($curl === False)
{
die('Fatal error initiating CURL');
}
curl_setopt_array($curl,
array(CURLOPT_HTTPGET => True,
CURLOPT_RETURNTRANSFER => True,
CURLOPT_FOLLOWLOCATION => True,
CURLOPT_URL => $gatewayURL . $parameters
));
$rawJasonData = curl_exec($curl);
curl_close($curl);
if ($rawJasonData === False)
The code seems to be OK—although I will admit that this is my first time using CURL—because the returned JSON data is echoed.
I want to capture it in a variable, how do I do that (without resorting to output buffering)?
[Update] I am certain that I don't var_dump() or echo the result myself. Neither 1 instead of True, nor uppercase TRUE make any difference.
I am developing locally, but using an entry in the Windows HOST file in my URL, not localhost.
Not sure why cURL isn't working for you, but since you are just making a simple GET request, why not just do:
$rawJasonData = file_get_contents($gatewayURL.$parameters);
Likely a non issue, but:
curl_setopt_array($curl,
array(CURLOPT_HTTPGET => 1,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_HEADER => 0,
CURLOPT_URL => $gatewayURL . $parameters));
In previous versions of PHP, I encountered significant issues with using True when setting curl options. Give 1 a shot and see what happens. This worked for me, but it could have been due to the environment I was working in. Just wanting to mention this in case you have some weird environment (like I had) that caused the most odd problems.
As for personal preference, I prefer using the following method to set options:
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_CURLOPT_HEADER, 1);
curl_setopt($curl, CURLOPT_CURLOPT_HTTPGET, 1);
As for your question -- I'd remove CURLOPT_FOLLOWLOCATION as that will follow redirects and you shouldn't have any in your case.
I suspect that CURLOPT_FOLLOWLOCATION is the issue here.
The big issue I am seeing with your code is the use of the first uppercase in True and False when it should be TRUE and FALSE. Here is my refactored version of your code that should work:
$curl = curl_init();
if (!$curl) {
die('Fatal error initiating CURL');
}
$curl_options = array();
$curl_options['CURLOPT_HTTPGET'] = TRUE;
$curl_options['CURLOPT_RETURNTRANSFER'] = TRUE;
$curl_options['CURLOPT_HTTPGET'] = TRUE;
$curl_options['CURLOPT_HTTPHEADER'] = array('Content-Type: application/json', 'Accept: application/json');
$curl_options['CURLOPT_URL'] = $gatewayURL . $parameters;
curl_setopt_array($curl, $curl_options);
$rawJasonData = curl_exec($curl);
curl_close($curl);
if (!$rawJasonData)
I added CURLOPT_HTTPGET as TRUE to force GET behavior from curl as well as JSON related headers in CURLOPT_HTTPHEADER.
Past all of that you have checks that were set as === False which are a bit excessive. Simply setting a if (!$curl) { and an if (!$rawJasonData) would work as expected.
If that still somehow does not work, change the TRUE values to a 1 like this:
$curl_options = array();
$curl_options['CURLOPT_HTTPGET'] = 1;
$curl_options['CURLOPT_RETURNTRANSFER'] = 1;
$curl_options['CURLOPT_HTTPGET'] = 1;

Send AJAX-like post request using PHP only

I'm currently working on some automatization script in PHP (No HTML!).
I have two PHP files. One is executing the script, and another one receive $_POST data and returns information.
The question is how from one PHP script to send POST to another PHP script, get return variables and continue working on that first script without HTML form and no redirects.
I need to make requests a couple of times from first PHP file to another under different conditions and return different type of data, depending on request.
I have something like this:
<?php // action.php (first PHP script)
/*
doing some stuff
*/
$data = sendPost('get_info');// send POST to getinfo.php with attribute ['get_info'] and return data from another file
$mysqli->query("INSERT INTO domains (id, name, address, email)
VALUES('".$data['id']."', '".$data['name']."', '".$data['address']."', '".$data['email']."')") or die(mysqli_error($mysqli));
/*
continue doing some stuff
*/
$data2 = sendPost('what_is_the_time');// send POST to getinfo.php with attribute ['what_is_the_time'] and return time data from another file
sendPost('get_info' or 'what_is_the_time'){
//do post with desired attribute
return $data; }
?>
I think i need some function that will be called with an attribute, sending post request and returning data based on request.
And the second PHP file:
<?php // getinfo.php (another PHP script)
if($_POST['get_info']){
//do some actions
$data = anotherFunction();
return $data;
}
if($_POST['what_is_the_time']){
$time = time();
return $time;
}
function anotherFunction(){
//do some stuff
return $result;
}
?>
Thanks in advance guys.
Update: OK. the curl method is fetching the output of php file. How to just return a $data variable instead of whole output?
You should use curl. your function will be like this:
function sendPost($data) {
$ch = curl_init();
// you should put here url of your getinfo.php script
curl_setopt($ch, CURLOPT_URL, "getinfo.php");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$result = curl_exec ($ch);
curl_close ($ch);
return $result;
}
Then you should call it this way:
$data = sendPost( array('get_info'=>1) );
I will give you some example class , In the below example you can use this as a get and also post call as well. I hope this will help you.!
/*
for your reference . Please provide argument like this,
$requestBody = array(
'action' => $_POST['action'],
'method'=> $_POST['method'],
'amount'=> $_POST['amount'],
'description'=> $_POST['description']
);
$http = "http://localhost/test-folder/source/signup.php";
$resp = Curl::postAuth($http,$requestBody);
*/
class Curl {
// without header
public static function post($http,$requestBody){
$curl = curl_init();
// Set some options - we are passing in a useragent too here
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => $http ,
CURLOPT_USERAGENT => 'From Front End',
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $requestBody
));
// Send the request & save response to $resp
$resp = curl_exec($curl);
// Close request to clear up some resources
curl_close($curl);
return $resp;
}
// with authorization header
public static function postAuth($http,$requestBody,$token){
if(!isset($token)){
$resposne = new stdClass();
$resposne->code = 400;
$resposne-> message = "auth not found";
return json_encode($resposne);
}
$curl = curl_init();
$headers = array(
'auth-token: '.$token,
);
// Set some options - we are passing in a useragent too here
curl_setopt_array($curl, array(
CURLOPT_HTTPHEADER => $headers ,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => $http ,
CURLOPT_USERAGENT => 'From Front End',
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $requestBody
));
// Send the request & save response to $resp
$resp = curl_exec($curl);
// Close request to clear up some resources
curl_close($curl);
return $resp;
}
}

Categories