PHP cURL required only to send and not wait for response - php

I need a PHP cURL configuration so that my script is able to send requests and ignore the answers sent by the API.
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST,count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string);
// curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
//curl_setopt($ch, CURLOPT_TIMEOUT_MS, 100);
$result = curl_exec($ch);
echo $result;
curl_close ($ch);
I tried adding:
// curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
//curl_setopt($ch, CURLOPT_TIMEOUT_MS, 100);
But its not working properly and the API webserver is not receiving the requests.
The reason for this is I am sending large amount of requests to the API therefore my script is very slow because it waits for each and every request.
Any help is appreciated.

Sender file example ./ajax/sender.php
Script sending POST -> it makes full request to host, but it doesn't wait on answer from server : CURLOPT_HEADER(0) we dont needs headers from server) and CURLOPT_RETURNTRANSFER (false) we don't needs data from server.CURLOPT_TIMEOUT - Extra procteted : We waiting after sent only 1ms on respond server, this is extra quaranty to not wait any more ms if server keep us. ### NOTE ### HTTP1.1 has one package max 16kb. HTTP2 has 36kb one pacakge. If POST are more biggest, server will be send with many packages in series = $SIZE%16kb
$url = 'https://127.0.0.1/ajax/received.php';
$curl = curl_init();
$post['test'] = 'examples daata'; // our data todo in received
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt ($curl, CURLOPT_POST, TRUE);
curl_setopt ($curl, CURLOPT_POSTFIELDS, $post);
curl_setopt($curl, CURLOPT_USERAGENT, 'api');
//curl_setopt($curl, CURLOPT_TIMEOUT, 1); //if your connect is longer than 1s it lose data in POST better is finish script in recevie
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, false);
curl_setopt($curl, CURLOPT_FORBID_REUSE, true);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 1);
curl_setopt($curl, CURLOPT_DNS_CACHE_TIMEOUT, 100);
curl_setopt($curl, CURLOPT_FRESH_CONNECT, true);
curl_exec($curl);
curl_close($curl);
Received file example ./ajax/received.php
ignore_user_abort(true); //if connect is close, we continue php script in background up to script will be end
header("Connection: close\r\n");
header("Content-Encoding: none\r\n");
header("Content-Length: 1");
### we just close connect above if webbrowser, or request waiting on answer ( we know we set CURLOP to not wait) ###
ob_end_clean(); //just flush all content if exists to request. If server still waiting on answer.
//HERE all script doing in background: Example
$this->db->query('UPDATE new_hook_memory SET new=new+1 WHERE id=1');
EDIT 2019 if you using fastcgi just finish fastcgi and browser close connection but script still will be working up to end.
How finish script: PHP mod_fcgi with fastcgi_finish_request();
For Apache2:
ob_end_flush();
flush();
For php-fpm
fastcgi_finish_request(); $this->db->query('UPDATE new_hook_memory SET new=new+1 WHERE id=1');
Old version:

These two solutions work well for me
( Of course it has been a long time, but I don't think this question is outdated )
using file_get_contents:
//url of php to be called
$url = "example.php/test?id=1";
//this will set the minimum time to wait before proceed to the next line to 1 second
$ctx = stream_context_create(['http'=> ['timeout' => 1]]);
file_get_contents($url,null,$ctx);
//the php will read this after 1 second
using cURL:
//url of php to be called
$url = "example.php/test?id=1";
$test = curl_init();
//this will set the minimum time to wait before proceed to the next line to 100 milliseconds
curl_setopt_array($test,[CURLOPT_URL=>$url,CURLOPT_TIMEOUT_MS=>100,CURLOPT_RETURNTRANSFER=>TRUE]);
curl_exec($test);
//this line will be executed after 100 milliseconds
curl_close ($test);
in both case the called php must set ignore_user_abort(true).
And the result will not be printed in both case, but be careful with the timeout you will set, it needs to be greater than the time that the called php needs to start yielding results.

If possible you can run wget in background (using exec)

There was some frustration in finding a solution that actually works, so I ended up building a service based on fsockopen() that can handle both GET and POST requests, without being blocking.
Below is the service class:
class NonBlockingHttpClientService {
private $method = 'GET';
private $params = [];
private $port = 80;
private $host;
private $path;
private $post_content;
public function isPost(): bool
{
return ($this->method === 'POST');
}
public function setMethodToPost(): NonBlockingHttpClientService
{
$this->method = 'POST';
return $this;
}
public function setPort(int $port): NonBlockingHttpClientService
{
$this->port = $port;
return $this;
}
public function setParams(array $params): NonBlockingHttpClientService
{
$this->params = $params;
return $this;
}
private function handleUrl(string $url): void
{
$url = str_replace(['https://', 'http://'], '', $url);
$url_parts = explode('/', $url);
if(count($url_parts) < 2) {
$this->host = $url_parts[0];
$this->path = '/';
} else {
$this->host = $url_parts[0];
$this->path = str_replace($this->host, '', $url);
}
}
private function handleParams(): void
{
if(empty($this->params)) return;
if($this->isPost()) {
$this->post_content = http_build_query($this->params);
} else {
/*
if you want to specify the params as an array for GET request, they will just be
appended to the path as a query string
*/
if(strpos($this->path, '?') === false) {
$this->path .= '?' . ltrim($this->arrayToQueryString($this->params), '&');
} else {
$this->path .= $this->arrayToQueryString($this->params);
}
}
}
private function arrayToQueryString(array $params): string
{
$string = '';
foreach($params as $name => $value) {
$string .= "&$name=" . urlencode($value);
}
return $string;
}
public function doRequest(string $url): bool
{
$this->handleUrl($url);
$this->handleParams();
$host = $this->host;
$path = $this->path;
$fp = fsockopen($host, $this->port, $errno, $errstr, 1);
if (!$fp) {
$error_message = __CLASS__ . ": cannot open connection to $host$path : $errstr ($errno)";
echo $error_message;
error_log($error_message);
return false;
} else {
fwrite($fp, $this->method . " $path HTTP/1.1\r\n");
fwrite($fp, "Host: $host\r\n");
if($this->isPost()) fwrite($fp, "Content-Type: application/x-www-form-urlencoded\r\n");
if($this->isPost()) fwrite($fp, "Content-Length: " . strlen($this->post_content) . "\r\n");
fwrite($fp, "Connection: close\r\n");
fwrite($fp, "\r\n");
if($this->isPost()) fwrite($fp, $this->post_content);
return true;
}
}
}
It can be used like this:
$req = new NonBlockingHttpClientService();
$req->setMethodToPost(); //default is GET, so just omit this for GET requests
$req->setParams([
'test2' => 'aaaa', //if parameters are specified both with setParams() and in the query string, for GET requests, params specified with setParams() will take precedence
'test3' => 'bbbb',
'time' => date('H:i:s')
]);
$req->doRequest('test.localhost/some_path/slow_api.php?test1=value1&test2=value2');
And the slow_api.php file, can be something like this.
<?php
error_log('start');
sleep(10);
error_log(print_r($_REQUEST, 1) . 'end');
I find it easier to monitor (tail -f) the error log in order to see what is happening.

How can you tell if the request succeeded or not? You need to wait for at least the status code from the server to determine that. If latency is the issue, look at the curl multi API to perform multiple requests in parallel. You should be able to set a write callback function to abort reception of returned data once the status code has been returned.

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 1);
curl_exec($ch);
curl_close($ch);
That works well for me.
Tested on PHP 7.1.14 Windows

A bit late now but the solution to this for anyone interested is that CURLOPT_RETURNTRANSFER needs to be set to TRUE, not false. That way the curl_exec function returns a value immediately rather than waiting for the request to complete before returning - i.e. it acts asynchronously rather than synchronously.
Example:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

If you use Linux, you can use shell_exec in your PHP and send the result of curl to dev/null. By this method, you don't receive any answer and after sending PHP goes to the next line and Linux executes your command in the background. You should use this method if the answer is not important to you.
This is an example:
shell_exec("curl 'http://domian.com/message?text=$text' > /dev/null 2>/dev/null &")
Note: You can add any curl option like header or post method or proxy as your need.

Related

Simply posting variables through GET in cURL

so I'm trying to make a small API here. I'll be only sending some information via header (get params) and I'm not using any POST parameters.
Here's the code that I've written.
function sendSMS($message, $number)
{
/*** Connection Params **/
/*** Build the request parameters ***/
$service="sms_api_call_receiver.php";
$number="1212";
$message="asas";
$result = sendPost("https://www.domain.com/smsapp/" . $service . "?message=".urlencode($message)."&number=".$number);
return $result;
}//function
function sendPost($Url)
{
// Initialisation
$ch=curl_init();
// Set parameters
curl_setopt($ch, CURLOPT_URL, $Url);
// Return a variable instead of posting it directly
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// Active the POST method
//curl_setopt($ch, CURLOPT_POST, 1) ;
// Request
//curl_setopt($ch, CURLOPT_POSTFIELDS, $strRequest);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
// execute the connexion
$result = curl_exec($ch);
// Close it
//return curl_error($ch);
curl_close($ch);
return $result;
}
On the receiver file, I have this code :-
if(isset($_GET['message']))
{
return true;
}
else
{
return "12212";
}
But when I test, the output I get is :-
string '' (length=0)
What am I doing wrong here?
Troubleshooting
I tried to see if curl_error returned anything. But I could see nothing.
Any suggestions here would be helpful.
Are you sure there is something wrong there? If $_GET['message'] is set (in your test example it is) the script (sms_api_call_receiver.php) returns true and stops the execution.
Because it is HTTP request, and the response is empty, you'll get as result in the sendSMS() function string with 0 length.
to get something as response in sendSMS you need to print in sms_api_call_receiver.php instead of using return

PHP use socks5 proxy with fsockopen ssl

I'm trying to open a HTTPs page using php through a socks5 proxy, but I can't use curl, because I have to be able to read each line of the response.
To do that, I'm using this PHP class: http://www.phpkode.com/source/s/socksed/socksed.php, but if I start a connection on port 443, and send a HTTP POST request with params, nginx sends me back this message:
400 the plain http request was sent to https port
I tried to change that part of the code #fsockopen("tcp:// to #fsockopen("ssl://, but then I can't open the page.
If you're ok with using curl, the following should help achieve what you're after:
// create the curl buffered reader object with a connection to a socks5 proxy on localhost port 8888
$cbr = new \CurlBufferedReader(array(
CURLOPT_PROXY => 'socks5://127.0.0.1:8888',
// disable ssl certificate verification, you probably don't need this so I've commented it out
//CURLOPT_SSL_VERIFYPEER => false
));
// gets the body at the url up until the point specified by the callback function
$body = $cbr->get('https://stackoverflow.com/questions/24249029/php-use-socks5-proxy-with-fsockopen-ssl',
/**
* The callback function to determine whether to continue reading the body sent by the remote server
* #param string $body
*/
function (&$body) {
if (($off = strpos($body, "\nTo do that,")) !== false) {
// truncate body so that we have everything up until the newline before the string "To do that,"
$body = substr($body, 0, $off + 1);
}
return $off === false; // continue reading while true
});
echo $body;
And the related class:
class CurlBufferedReader {
private $body = false;
private $callback;
private $ch;
public function __construct(array $curlopts = array()) {
$this->ch = curl_init();
curl_setopt_array($this->ch, $curlopts + array(
// general curl options
CURLOPT_CONNECTTIMEOUT => 30,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 10,
CURLOPT_RETURNTRANSFER => true,
// specific options to abort the connection early
CURLOPT_BUFFERSIZE => 8192,
CURLOPT_WRITEFUNCTION => array($this, 'writeFunction')
));
}
public function get($url, $callback = null) {
curl_setopt($this->ch, CURLOPT_URL, $url);
$this->callback = $callback;
if (!($success = $this->exec())) {
// errno 23 when aborted by the client
if ($this->getErrno() !== 23) {
$this->body = false;
}
}
return $this->body;
}
public function getBody() {
return $this->body;
}
public function getError() {
return curl_error($this->ch);
}
public function getErrno() {
return curl_errno($this->ch);
}
private function exec() {
$status = curl_exec($this->ch);
$this->callback = null;
return $status;
}
private function writeFunction($ch, $buffer) {
$this->body .= $buffer;
if ($this->callback && !call_user_func_array($this->callback, array(&$this->body))) {
$written = -1; // user callback requested abort
} else {
$written = strlen($buffer);
}
return $written;
}
}
It works by reading 8,192 bytes at a time from the remote server. A user function is called to read the total body received upon each read event. The user function must return false when it wishes to abort the connection. It's also important to note that $body is a reference. Therefore any changes you make to it will affect the string received by the CurlBufferedReader::get method.
Try this:
$ch = curl_init();
curl_setopt($ch, CURLOPT_PROXY, $proxy);
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
//curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxyauth);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_PROXYTYPE, 7);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_URL, $url);
$curl_scraped_page = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);

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;

Reading POST data in PHP from cUrl

I am using cUrl in PHP to request from some external service.
Interesting enough, the server is responding with raw "multipart/form-data" instead of binary file data.
My website is using a shared hosting, therefore PECL HTTP is not an option.
Is there a way to parse this data with PHP?
Sample code:
$response = curl_exec($cUrl);
/* $response is raw "multipart/form-data" string
--MIMEBoundaryurn_uuid_DDF2A2C71485B8C94C135176149950475371
Content-Type: application/xop+xml; charset=utf-8; type="text/xml"
Content-Transfer-Encoding: binary
(xml data goes here)
--MIMEBoundaryurn_uuid_DDF2A2C71485B8C94C135176149950475371
Content-Type: application/zip
Content-Transfer-Encoding: binary
(binary file data goes here)
*/
EDIT: I tried piping the response to a localhost HTTP request, but the respond data is likely to exceed the allowed memory size in PHP process. Expending mem limit is not very practical, this action also dramatically reduces the server performance dramatically.
If there is no alternatives to the original question, you may suggest a way to handle very large POST requests, along with XML parsing, in terms of streams in PHP.
I know this would be hard, please comment. I am open for discussions.
if you need the zip file from the response I guess you could just write a tmp file to save the curl response to, and stream that as a workaround:
Never tried that with multipart curls, but I guess it should work.
$fh = fopen('/tmp/foo', 'w');
$cUrl = curl_init('http://example.com/foo');
curl_setopt($cUrl, CURLOPT_FILE, $fh); // redirect output to filehandle
curl_exec($cUrl);
curl_close($cUrl);
fclose($fh); // close filehandle or the file will be corrupted
if you do NOT need anything but the xml part of the response you might want to disable headers
curl_setopt($cUrl, CURLOPT_HEADER, FALSE);
and add option to only accept xml as a response
curl_setopt($cUrl, CURLOPT_HTTPHEADER, array('Accept: application/xml'));
//That's a workaround since there is no available curl option to do so but http allows that
[EDIT]
A Shot in the dark...
can you test with these curlopt settings to see if modifiying these help anything
$headers = array (
'Content-Type: multipart/form-data; boundary=' . $boundary,
'Content-Length: ' . strlen($requestBody),
'X-EBAY-API-COMPATIBILITY-LEVEL: ' . $compatLevel, // API version
'X-EBAY-API-DEV-NAME: ' . $devID,
'X-EBAY-API-APP-NAME: ' . $appID,
'X-EBAY-API-CERT-NAME: ' . $certID,
'X-EBAY-API-CALL-NAME: ' . $verb,
'X-EBAY-API-SITEID: ' . $siteID,
);
$cUrl = curl_init();
curl_setopt($cUrl, CURLOPT_URL, $serverUrl);
curl_setopt($cUrl, CURLOPT_TIMEOUT, 30 );
curl_setopt($cUrl, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($cUrl, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($cUrl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($cUrl, CURLOPT_POST, 1);
curl_setopt($cUrl, CURLOPT_POSTFIELDS, $requestBody);
curl_setopt($cUrl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($cUrl, CURLOPT_FAILONERROR, 0 );
curl_setopt($cUrl, CURLOPT_FOLLOWLOCATION, 1 );
curl_setopt($cUrl, CURLOPT_HEADER, 0 );
curl_setopt($cUrl, CURLOPT_USERAGENT, 'ebatns;xmlstyle;1.0' );
curl_setopt($cUrl, CURLOPT_HTTP_VERSION, 1 ); // HTTP version must be 1.0
$response = curl_exec($cUrl);
if ( !$response ) {
print "curl error " . curl_errno($cUrl ) . PHP_EOL;
}
curl_close($cUrl);
[EDIT II]
This is just a try, as mentioned I cannot get my curled pages to respond with a multipart form data. So be gentle with me here ;)
$content_type = ""; //use last know content-type as a trigger
$tmp_cnt_file = "tmp/tmpfile";
$xml_response = ""; // this will hold the "usable" curl response
$hidx = 0; //header index.. counting the number of different headers received
function read_header($cUrl, $string)// this will be called once for every line of each header received
{
global $content_type, $hidx;
$length = strlen($string);
if (preg_match('/Content-Type:(.*)/', $string, $match))
{
$content_type = $match[1];
$hidx++;
}
/*
should set $content_type to 'application/xop+xml; charset=utf-8; type="text/xml"' for the first
and to 'application/zip' for the second response body
echo "Header: $string<br />\n";
*/
return $length;
}
function read_body($cUrl, $string)
{
global $content_header, $xml_response, $tmp_cnt_file, $hidx;
$length = strlen($string);
if(stripos ( $content_type , "xml") !== false)
$xml_response .= $string;
elseif(stripos ($content_type, "zip") !== false)
{
$handle = fopen($tmp_cnt_file."-".$hidx.".zip", "a");
fwrite($handle, $string);
fclose($handle);
}
/*
elseif {...} else{...}
depending on your needs
echo "Received $length bytes<br />\n";
*/
return $length;
}
and of course set the proper curlopts
// Set callback function for header
curl_setopt($cUrl, CURLOPT_HEADERFUNCTION, 'read_header');
// Set callback function for body
curl_setopt($cUrl, CURLOPT_WRITEFUNCTION, 'read_body');
don't forget to NOT save the curl response to a variable because of the memory issues,
hopefully all you need will be in the $xml_response above anyways.
//$response = curl_exec($cUrl);
curl_exec($cUrl);
And for parsing your code you can refer to $xml_response and the temp files you created starting with tmp/tmpfile-2 in this scenario. Again, I have not been able to test the code above in any way. So this might not work (but it should imho ;))
[EDIT III]
Say we want curl to write all incoming data directly to another (outgoing) stream, in this case a socket connection
I'm not sure if it is as easy as this:
$fs = fsockopen($host, $port, $errno, $errstr);
$cUrl = curl_init('http://example.com/foo');
curl_setopt($cUrl, CURLOPT_FILE, $fs); // redirect output to sockethandle
curl_exec($cUrl);
curl_close($cUrl);
fclose($fs); // close handle
else we will have to use our known write and header functions with just a little trick
//first open the socket (before initiating curl)
$fs = fsockopen($host, $port, $errno, $errstr);
// now for the new callback function
function socket_pipe($cUrl, $string)
{
global $fs;
$length = strlen($string);
fputs($fs, $string); // add NOTHING to the received line just send it to $fs; that was easy wasn't it?
return $length;
}
// and of course for the CURLOPT part
// Set callback function for header
curl_setopt($cUrl, CURLOPT_HEADERFUNCTION, 'socket_pipe');
// Set the same callback function for body
curl_setopt($cUrl, CURLOPT_WRITEFUNCTION, 'socket_pipe');
// do not forget to
fclose($fs); //when we're done
The thing is, not editing the result and simply piping it to $fs will make it necessary that apache is listening on a certain port which you then assign your script to.
Or you will need to add ONE header line directly after fsockopen
fputs($fp, "POST $path HTTP/1.0\n"); //where path is your script of course
I'm sorry i can't help much because you did not put much code but i remember i was having a similar issue when i was playing with curl_setopt options.
Did you use CURLOPT_BINARYTRANSFER?
From php documentation -> CURLOPT_BINARYTRANSFER-> TRUE to return the raw output when CURLOPT_RETURNTRANSFER is used.
just set CURLOPT_RETURNTRANSFER CURLOPT_POST
$c = curl_init($url);
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
curl_setopt($c, CURLOPT_CONNECTTIMEOUT, 1);
curl_setopt($c, CURLOPT_TIMEOUT, 1);
curl_setopt($c, CURLOPT_POST, 1);
curl_setopt($c, CURLOPT_POSTFIELDS,
array());
$rst_str = curl_exec($c);
curl_close($c);
You can re-assemble you Binary data doing something like this, I hope it helps.
$file_array = explode("\n\r", $file, 2);
$header_array = explode("\n", $file_array[0]);
foreach($header_array as $header_value) {
$header_pieces = explode(':', $header_value);
if(count($header_pieces) == 2) {
$headers[$header_pieces[0]] = trim($header_pieces[1]);
}
}
header('Content-type: ' . $headers['Content-Type']);
header('Content-Disposition: ' . $headers['Content-Disposition']);
echo substr($file_array[1], 1);
If you don't need binary data, have you tried below?
curl_setopt($c, CURLOPT_NOBODY, true);

CURLOPT_TIMEOUT , is there "else" function?

<?php
function get_random_proxy()
{
srand ((double)microtime()*1000000);
$f_contents = file ("proxy.txt");
$line = $f_contents[array_rand ($f_contents)];
return $line;
}
$proxy = get_random_proxy();
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "example.com");
curl_setopt($ch, CURLOPT_PROXY,$proxy);
curl_setopt($ch, CURLOPT_TIMEOUT ,30);
curl_exec($ch);
curl_close($ch);
?>
curl will close connection if can not connect within the 30 seconds.
as you can see, i'm using proxy list. however, some proxy ips sometimes have problems to connect within the 30 seconds, and curl is closing connection when can not load in 30 seconds.
i wanna try another ip for curl connect if curl timeout reached. right now, curl is closing everything if ip isn't working. i wanna try another ip. well, could you please suggest me a function?
edited for #rubayeet. added new proxy function
You just have to use curl_errno to test if CURLE_OPERATION_TIMEDOUT occured
function get($url, $proxy){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_PROXY,$proxy);
curl_setopt($ch, CURLOPT_TIMEOUT ,30);
$response = curl_exec($ch);
curl_close($ch);
return $response
}
$url = 'example.com';
while(true) {
$proxy = get_random_proxy();
$response = get($url, $proxy);
if ($response === False) continue;
else break;
}
//do something with $response
You have to create a new curl session to connect to another proxy. So put a foreach loop around your code and loop through your proxy array.
Also you can use curl_errno() and curl_error() to check for an error (like your timeout).
Maybe it would be useful to set CURLOPT_RETURNTRANSFER and load it into a var to modify or work on it.

Categories