17

When I run curl on a particular url, the site stops responding and doesn't generate an error, despite my having set error reporting to on. I've tried setting the curl timeouts to low values, and it generates an error then, so I know its not timing out.

The main thing I want to know is, how could that even happen, and how can I figure out why?

The url I'm trying to access is a call to the Factual api, and the url I'm using here

(http://api.factual.com/v2/tables/bi0eJZ/read?api_key=*apikey*&filters={"category":"Automotive","$loc":{"$within":{"$center":[[41,-74],80467.2]}})

Works when you put it in a browser. The php script works as intended if you change the latitude and longitude to essentially any other values.

error_reporting(E_ALL);
ini_set('display_errors', '2');
$url="http://api.factual.com/v2/tables/bi0eJZ/read?api_key=*apikey*&filters={\"category\":\"Automotive\",\"\$loc\":{\"\$within\":{\"\$center\":[[41,-74],80467.2]}},\"website\":{\"\$blank\":false}}";
Echo "\n\n1";

$ch = curl_init($url);
Echo 2;
curl_setopt($ch, CURLOPT_HEADER, 0);
Echo 3;
curl_setopt($ch, CURLOPT_POST, 1);
Echo 4;
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT,15);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT,30);
Echo 5;
$output = curl_exec($ch) or die("hhtrjrstjsrjt".curl_error($ch));   
Echo 6;
curl_close($ch);
Echo "out: ".$output;
George G
  • 7,443
  • 12
  • 45
  • 59
John
  • 171
  • 1
  • 4
  • 6
    You might try setting a different useragent; we've had spamming problems before, and we do interesting things with useragents we don't like. – Glen Solsberry Feb 14 '11 at 17:41
  • 2
    Also, It might not be a good idea to post your API keys – DFectuoso Feb 14 '11 at 17:48
  • 3
    One thing: `$output = curl_exec($ch) or die("hhtrjrstjsrjt".curl_error($ch));` will not do what you expect. Basically, it's doing `$output = (curl_exec($ch) or die("hhtrjrstjsrjt".curl_error($ch)));` in that it's returning a boolean instead of a string. Instead, either move the error check to the next line, or explicitly group it like this: `($output = curl_exec($ch)) or die("hhtrjrstjsrjt".curl_error($ch));` – ircmaxell Feb 14 '11 at 17:48
  • ircmaxell, the main thing thats confusing me here is that it never gets to the next line, even without the "or die". Changing the useragent to that of my browser doesn't seem to do anything either. – John Feb 15 '11 at 02:57
  • I'm having the same problem. No errors are thrown, and the script just dies. – HappyDeveloper Mar 26 '11 at 05:46
  • Do you get those all `echo`ed numbers? – revo Jul 13 '16 at 16:41
  • I think that your WEB-server (Apache, PHP-FPM, etc) stops execution of your script in reason of timeout, memory limit, etc. Try retrieve info from webserver's logs. I really think answer is hidden there. – Victor Perov Jul 18 '16 at 16:12
  • Need more debugging info. Try with `wget` from the CLI, see if get same issue. Try with `curl` from the CLI see if get same issue. – spinkus Jul 19 '16 at 09:09
  • Please do the following: use fsockopen to connect to the server and send every single parameter manually and listen to what it returns. It's really helpful to know what actually is returned and when it's returned by the server. Tell us the results so we can help you better – A. Kalantari Jul 19 '16 at 09:28

7 Answers7

5

It looks like you have some mistakes in your PHP configuration file.

To fix your errors you must edit your php.ini file.

For displaying errors in development mode, change the error_reporting value to E_ALL.

error_reporting=E_ALL

Then you have to enable the cURL extension. To enable it in your php.ini, yous have to uncomment the following line:

extension=php_curl.dll

Once you edited this values, don't forget to restart your webserver (Apache or Nginx)

Also I agree with my colleagues, you should url_encode your JSON string.

From my point of view the code should be:

<?php
ini_set('display_errors', '1');
error_reporting(E_ALL);

$apiKey = '*apikey*';
$filters = '{"category":"Automotive","$loc":{"$within":{"$center":[[41,-74],80467.2]}},"website":{"$blank":false}}';
$params = '?api_key=' . $apiKey . '&filters=' . url_encode($filters);

$url = 'http://api.factual.com/v2/tables/bi0eJZ/read';
$url .= $params;

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$output = curl_exec($ch) or die("cURL Error" . curl_error($ch));   
curl_close($ch);

echo "out: " . $output;

EDIT:

Another approach could be to use the Official PHP driver for the Factual API: Official PHP driver for the Factual API

It provides a Debug Mode with a cURL Debug Output and a Exception Debug Output.

TwystO
  • 2,456
  • 2
  • 22
  • 28
4

In my case the curl failure was due to the fact that the hosting provider had replaced Apache with Litespeed, and litespeed was terminating the process during the curl request.

The php.ini settings didn't fix this as lsphp was getting terminated at 30 seconds every time.

We had a long chat, and I convinced them their server was actually broken (eventually).

To make this clearer for other people who might have a similar or related problem:
My PHP script was running, and no error was being logged in PHP because the entire PHP process, including the error logger was being terminated by the web server.

Tim Ogilvy
  • 1,923
  • 1
  • 24
  • 36
4

Your url is not url_encoded as CURL is an external application escaping is necessary your browser will auto url_encode params on the URL however you could be breaking curl on the server and it is halting.

Try changing this:

$url="http://api.factual.com/v2/tables/bi0eJZ/read?api_key=*apikey*&filters={\"category\":\"Automotive\",\"\$loc\":{\"\$within\":{\"\$center\":[[41,-74],80467.2]}},\"website\":{\"\$blank\":false}}";

to:

$url_filters = '{"category":"Automotive","$loc":{"$within":{"$center":[[41,-74],80467.2]}},"website":{"$blank":false}}';

$url="http://api.factual.com/v2/tables/bi0eJZ/read?api_key=*apikey*&filters=".urlencode($url_filters);

However i do have some question is your call correct? the key of literlal "$loc" is that correct?

Updated to remove the need to backslash everything single quotes don't support variable replace and will allow double quotes without escaping them

bpoiss
  • 13,673
  • 3
  • 35
  • 49
Barkermn01
  • 6,781
  • 33
  • 83
4

For future benefit:

  1. Use urlencode for query parameters as your filters parameter contains many characters that are not safe/valid for URLs

  2. Use curl_getinfo() to see information about http_code and other useful information.

andyfeller
  • 905
  • 1
  • 7
  • 12
3

I have worked with CURL calls from vanilla PHP before. The CURL call is a part of the curl library. As other users have suggested, the url_encode($url) function would prepare the string for use by this particular class. If you do not run this, then you could pass in URLs which would break the handlers (e.g. by having invalid characters or URL syntax).

On top of this, it seems that you are trying to pass a JSON object directly into the URL of a page. I do not believe it is best practice to work with JSON packages in a curl call like this. If this is what you are looking to do, see this page: How do I POST JSON data with cURL?

Barkermn01
  • 6,781
  • 33
  • 83
Aaron Morefield
  • 952
  • 10
  • 18
3

this code is just for testing, just modify your code according to mine

<?php   

$useragent = 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.10 (KHTML, like Gecko)
Chrome/8.0.552.224: Safari/534.10'; // notice this
$url="http://api.factual.com/v2/tables/bi0eJZ/read?api_key=*apikey*&filters={\"category\":\"Automotive\",\"\$loc\":{\"\$within\":{\"\$center\":[[41,-74],80467.2]}},\"website\":{\"\$blank\":false}}";
$ch = curl_init(); // notice this

curl_setopt($ch, CURLOPT_URL, $url); // notice this
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

curl_setopt($ch, CURLOPT_USERAGENT, $useragent);




$contents = curl_exec($ch);
echo $contents;
?>
Jaanus
  • 16,161
  • 49
  • 147
  • 202
  • 9
    for those of us following along at home.. it'd be nice if you explained what you changed and why you changed it :) As you may notice - questions like this stay up on the site for a very long time and are found by other people, maybe months later, who have a similar problem and want to learn from it :) Thanks. – Taryn East Nov 29 '11 at 08:54
  • also does this work your using double quotes im sure curly bracers are for variables in php. should the parameters in the URL being URLencoded? – Barkermn01 Jul 18 '16 at 12:35
2

the fact that the script stop doing anything at all you can found it in here:

http://php.net/manual/en/function.set-time-limit.php

excerpt:

The set_time_limit() function and the configuration directive max_execution_time only affect the execution time of the script itself. Any time spent on activity that happens outside the execution of the script such as system calls using system(), stream operations, database queries, etc. is not included when determining the maximum time that the script has been running. This is not true on Windows where the measured time is real.

so basically, curl blocks all the php script and basically the only thing that is actually running is curl, so if it blocks forever, your site will no respond, thats why you need to use timeouts...

as how to avoid it, just use timeouts...

Javier Neyra
  • 1,239
  • 11
  • 12
  • This would normally be correct if PHP_CURL did not use CURL on the host system essentially doing a very fancy `exec("curl ....")` if curl halts for user input php will just wait and wait for it no matter how long you set the timeout to. – Barkermn01 Jul 22 '16 at 12:44