I have a random "hang without errors" while executing curl requests. I'm trying to detect the origin as the web server and php logs don't show any errors, so I tried to enable CURLOT_STDERR.
I have the following code:
$file = 'curl.txt';
$curl = curl_init();
$curl_log = fopen($file, 'rw');
var_export(is_writable($file));
$url = 'http://www.google.com';
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_VERBOSE => 1,
CURLOPT_STDERR => $curl_log,
CURLOPT_RETURNTRANSFER => 1
));
$response = curl_exec($curl);
rewind($curl_log);
$output= fread($curl_log, 2048);
echo '<pre>'. print_r($output, 1). '</pre>';
fclose($curl_log);
is_writable returns true, but curl execution dies with the following error:
curl_setopt_array(): the provided file handle is not writable
I'm running PHP 7.0.15 Fast CGI on a Windows Machine.
It seems the CURL user doesn't have write permissions, but I can write on that file using other PHP functions.
Thank you very much for your help hanshenrik.
var_dump(fwrite($curl_log,'test')); returned 0.
So I changed the line $curl_log = fopen($file, 'rw'); to $curl_log = fopen($file, 'a'); and problem solved.
Related
This is the URL that I am trying to get content from:
$url = 'http://mgcash.com/api/?a=get_offers&key=13658244dad4cfb3&country=US&ua=Mozilla/5.0%20%28Macintosh;%20Intel%20Mac%20OS%20X%2010.10;%20rv:35.0%29%20Gecko/20100101%20Firefox/35.0&format=json';
So I tried file_get_contents() and that one is working fine. Then I tried this function that always worked, but not in this case.
class SimpleCurl
{
public static function get($url, $params=array())
{
$url = $url . '?' . http_build_query($params, '', '&');
$ch = curl_init();
$options = [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_SSL_VERIFYPEER => false
];
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
}
Then I tried using terminal with following command:
curl -X GET "http://mgcash.com/api/?a=get_offers&key=13658244dad4cfb3&country=US&ua=Mozilla/5.0%20%28Macintosh;%20Intel%20Mac%20OS%20X%2010.10;%20rv:35.0%29%20Gecko/20100101%20Firefox/35.0&format=json"
And that worked. It returned correct JSON object, without any problems.
Can anyone please let me know how do you debug CURL and figure what is the problem here?
After further tests and debugging I noticed following. Since my project require JSON object I am passing that fetched CURL $content trough $json_data = json_decode($content); and it returns nothing. Blank!
But if I try to echo or print_r before it goes trough json_decode(), I am literraly getting some RAW information/text and not JSON object. What the...
You're not passing $params to the get function and your $url ends up like http://mgcash.com/api/?a=get_offers&key=13658244dad4cfb3&country=US&ua=Mozilla/5.0%20%28Macintosh;%20Intel%20Mac%20OS%20X%2010.10;%20rv:35.0%29%20Gecko/20100101%20Firefox/35.0&format=json? note the appended ?
You can change the get function to only concatenate the query string when $params is not empty, something like this:
...
if (!empty($params)){
$url = $url . '?' . http_build_query($params, '', '&');
}
You should use CURLOPT_VERBOSE to output debug information:
CURLOPT_VERBOSE - TRUE to output verbose information. Writes output to STDERR, or the file specified using CURLOPT_STDERR.
Though if you're running your script in a browser, you wouldn't see the verbose log, because by default it outputs all info to stderr (usually that output can be seen in your error.log).
So to see the logged info you should either look into your error.log, run your script in a terminal, or provide another file handler for cURL to output the log. In the most simple case you can just redirect the output to stdout as follows:
$options = [
CURLOPT_VERBOSE => true,
CURLOPT_STDERR => fopen('php://stdout', 'w'),
...
];
In this case you'd see your log in your browser. Or, alternatively, you can provide any other filename to fopen to output the log in a file.
Reference: http://php.net/manual/en/function.curl-setopt.php
I am currently attempting to make a function in my class which gets data from an external server.
I am able to get the data with CURL, but I do not want to use CURL to directly store it in a file.
This is semi difficult to explain so I will show you.
This is my function for getting the image:
function getCharacterPortrait($CharID, $size){
$url = "http://image.eveonline.com/character/{$CharID}_{$size}.jpg";
$ch = curl_init($url);
curl_setopt_array($ch, array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => "",
CURLOPT_AUTOREFERER => true,
));
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
So, what I want to do from here, is take the $data which is the raw image I presume, and store it in a .jpg in a specified file.
I have found a similar explanation for this using CURL, but CURL was used to directly store it. I would like the script that is calling the function to get the image to store the file.
Sorry if I am being a bit confusing, but I think you get the premise of what I am saying. If more explaining is needed please do say so.
How about this?
$a = implode('',#file('http://url/file.jpg'));
$h = fopen('/path/to/disk/file.jpg','wb');
fwrite($h,$a);
fclose($h);
Just write all the data cURL gave you to a file with file_put_contents() for example?
[your curl code...]
file_put_contents('localcopy.jpg', $data);
Edit:
Apparently there is also a cURL option to download to a file like:
$fp = fopen($path, 'w');
curl_setopt($ch, CURLOPT_FILE, $fp);
Found at http://www.phpriot.com/articles/download-with-curl-and-php
Use it
$url = "http://image.eveonline.com/character/{$CharID}_{$size}.jpg";
$local_path = "myfolder/{$CharID}_{$size}.jpg";
$file = file_get_contents($url);
file_put_contents($file, $local_path);
We're trying to debug some cURL errors on the server, and I would like to see the STDERR log. Currently, all we can see for our error is "error code: 7" and that we can't connect to target server. We have contacted the host and made special rule to open the port we need and we're even ignoring the certificate for the time being.
Still, we can't connect. I need to debug this, but I can't see any pertinent information on my end.
The lines mentioning "VERBOSE" and "STDERR" are the most important, I think. Nothing is written to $curl_log. What am I doing wrong? Following the manuals logic, this should be correct...
PHP in use:
<?php
$curl = curl_init();
$curl_log = fopen("curl.txt", 'w');
$url = "http://www.google.com";
curl_setopt_array($curl, array(
CURLOPT_URL => $url, // Our destination URL
CURLOPT_VERBOSE => 1, // Logs verbose output to STDERR
CURLOPT_STDERR => $curl_log, // Output STDERR log to file
CURLOPT_SSL_VERIFYPEER => 0, // Do not verify certificate
CURLOPT_FAILONERROR => 0, // true to fail silently for http requests > 400
CURLOPT_RETURNTRANSFER => 1 // Return data received from server
));
$output = fread($curl_log, 2048);
echo $output; // This returns nothing!
fclose($curl_log);
$response = curl_exec($curl);
//...restofscript...
?>
From PHP manual: http://php.net/manual/en/function.curl-setopt.php
CURLOPT_VERBOSE TRUE to output verbose information. Writes output to STDERR
CURLOPT_STDERR An alternative location to output errors to instead of STDERR.
It is not a permission issue either, I have set file and script permissions to 777 on server side and my local client is windows and has never cared about permission settings (it's only for dev anyway).
You are making couple mistakes in your example:
1) you have to call curl_exec() prior to reading from the "verbose log", because curl_setopt() doesn't perform any action, so nothing can be logged prior to the curl_exec().
2) you are opening $curl_log = fopen("curl.txt", 'w'); only for write, so nothing could be read, even after you write to the file and rewind the internal file pointer.
So the correct shortened code should look like:
<?php
$curl = curl_init();
$curl_log = fopen("curl.txt", 'rw'); // open file for READ and write
$url = "http://www.google.com";
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_VERBOSE => 1,
CURLOPT_STDERR => $curl_log,
CURLOPT_RETURNTRANSFER => 1
));
$response = curl_exec($curl);
rewind($curl_log);
$output= fread($curl_log, 2048);
echo "<pre>". print_r($output, 1). "</pre>";
fclose($curl_log);
// ...
?>
NOTE: verbose log could be longer than 2048 bytes, so you could "fclose" the $curl_log after curl_exec() and then read the whole file with for example file_get_contents().
In that case, the point 2) should not be considered as mistake :-)
A bit late to the party, but this page still pops up high in Google, so let's go.
It seems that CURLOPT_VERBOSE doesn't log anything if CURLINFO_HEADER_OUT is also set to TRUE.
This is a know bug in PHP (#65348), and due to reasons they decided not to fix it.
Putting al above answers together, I use this function to make a Curl Post Request with loggin to a file option:
function CURLPostRequest($url, array $post = NULL, array $options = array(), $log_file = NULL){
$defaults = array(
CURLOPT_POST => 1,
CURLOPT_HEADER => 0,
CURLOPT_URL => $url,
CURLOPT_FRESH_CONNECT => 1,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_FORBID_REUSE => 1,
CURLOPT_TIMEOUT => 4,
CURLOPT_POSTFIELDS => http_build_query($post)
);
if (is_resource($log_file)){
$defaults[CURLOPT_VERBOSE]=1;
$defaults[CURLOPT_STDERR]=$log_file;
$defaults[CURLINFO_HEADER_OUT]=1;
}
$ch = curl_init();
curl_setopt_array($ch, ($options + $defaults));
if( ! $result = curl_exec($ch)){
throw new Exception(curl_error($ch));
}
if (is_resource($log_file)){
$info = curl_getinfo($ch);
if (isset($info['request_header'])){
fwrite($log_file, PHP_EOL.PHP_EOL.'* POST Content'.PHP_EOL.PHP_EOL);
fwrite($log_file, print_r($info['request_header'],true));
fwrite($log_file, http_build_query($post));
}
fwrite($log_file, PHP_EOL.PHP_EOL.'* Response Content'.PHP_EOL.PHP_EOL);
fwrite($log_file, $result.PHP_EOL.PHP_EOL);
}
curl_close($ch);
return $result;
}
Hope this help to someone.
I needed to close the file before being able to read it, this worked for me:
$filename = 'curl.txt';
$curl_log = fopen($filename, 'w'); // open file for write (rw, a, etc didn't help)
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_STDERR, $curl_log);
$result = curl_exec($ch);
fclose($curl_log);
$curl_log = fopen($filename, 'r'); // open file for read
$output= fread($curl_log, filesize($filename));
echo $output;
(PHP 5.6.0, Apache/2.2.15)
From php manual for function curl_setopt:
CURLOPT_FILE The file that the transfer should be written to. The default is STDOUT (the browser window).
You should put
$output = fread($curl_log, 2048);
echo $output; // This returns nothing!
fclose($curl_log);
after $response = curl_exec($curl); otherwise, file is closed during curl is executing.
I'm having trouble with this script. It works on my local server and test server, but doesn't seem to run correctly on my Rackspace server.
<?php
$path = "http://query.yahooapis.com/v1/public/yql?q=";
$path .= urlencode("SELECT * FROM feed WHERE url='http://feeds.feedburner.com/TMSEvents'");
$path .= "&format=json";
$feed = file_get_contents($path, true);
$feed = json_decode($feed); ?>
It is very simple, but I am getting the follow error message on the Rackspace server:
PHP Warning:
file_get_contents(http://query.yahooapis.com/v1/public/yql?q=SELECT+%2A+FROM+feed+WHERE+url%3D%27http%3A%2F%2Ffeeds.feedburner.com%2FTMSEvents%27&format=json)
[function.file-get-contents]:
failed to open stream: HTTP request failed! HTTP/1.0 500 999 This page
is currently unavailable
Anyone have any ideas why this would work on one server, but not on another? Thanks!
Look on this : http://codular.com/curl-with-php
Try Below code. Its working fine with tested :
<?php
$path = "http://query.yahooapis.com/v1/public/yql?q=";
$path .= urlencode("SELECT * FROM feed WHERE url='http://feeds.feedburner.com/TMSEvents'");
$path .= "&format=json";
// Get cURL resource
$curl = curl_init();
// Set some options - we are passing in a useragent too here
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => $path,
CURLOPT_USERAGENT => 'Codular Sample cURL Request'
));
// Send the request & save response to $resp
$feed = curl_exec($curl);
// Close request to clear up some resources
curl_close($curl);
$feed = json_decode($feed);
?>
I want to copy a file using PHP over http from a link in this format
http://myserver.com/?id=1234
if I open the link, the download of the file starts ...
So I assume that server redirects to a .mp3 file to start the download.
So how to copy/download the file from the remote server to to my server (localhost)?
Just to gove an example of what Victor is tlking about with cURL:
$options = array(
CURLOPT_FILE => '/local/path/for/file.mp3',
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_URL => 'http://myserver.com/?id=1234',
);
$ch = curl_init();
curl_setopt_array($ch, $options);
curl_exec($ch);
I'm assuming here that the remote server sends the complete file over HTTP. You could use a library such as curl to send an HTTP request and store the received data as a file (using CURLOPT_FILE).
If your local PHP server is correctly configured, you can also use copy to copy from a remote URL to a local path.
$handle = fopen("http://www.example.com/", "rb");
$contents = '';
while (!feof($handle)) {
$contents .= fread($handle, 8192);
}
fclose($handle);
from
http://php.net/manual/en/function.fread.php
Try using a notification callback (read here for mor informations http://www.php.net/manual/function.stream-notification-callback.php)
e.g. you could to this if you like to copy:
function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max)
{
if($notification_code == STREAM_NOTIFY_PROGRESS)
{
// save $bytes_transferred and $bytes_max to file or database
}
}
$ctx = stream_context_create();
stream_context_set_params($ctx, array("notification" => "stream_notification_callback"));
copy($remote_url,$Local_target,$ctx);
Another PHP file could read the saved $bytes_transferred and $bytes_max and show a nice progress bar.