117

How do these two pieces of code differ when accessing a REST API?

$result = file_get_contents('http://api.bitly.com/v3/shorten?login=user&apiKey=key&longUrl=url');

and

$ch = curl_init('http://api.bitly.com/v3/shorten?login=user&apiKey=key&longUrl=url');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);

They both produce the same result, judging by

print_r(json_decode($result))
TRiG
  • 9,687
  • 6
  • 54
  • 105
Salvador Dali
  • 199,541
  • 138
  • 677
  • 738
  • 3
    `cURL` is capable of much more than `file_get_contents`. That should be enough. –  Jun 16 '12 at 16:00
  • 21
    FWIW there's little difference with regards to speed. I've just finished fetching 5,000 URLs and saving their HTML to files (about 200k per file). I did half with curl and half with file_get_contents as an experiment and there was no discernible difference. – David Gilbertson Jun 17 '13 at 22:36
  • 8
    It is possible to send post data with file_get_contents, as long as you are using a version that supports stream context. – Chris Strickland Dec 29 '14 at 20:42

3 Answers3

137

file_get_contents() is a simple screwdriver. Great for simple GET requests where the header, HTTP request method, timeout, cookiejar, redirects, and other important things do not matter.

fopen() with a stream context or cURL with setopt are powerdrills with every bit and option you can think of.

MediaVince
  • 467
  • 8
  • 12
Xeoncross
  • 53,372
  • 77
  • 253
  • 360
  • 18
    To stay within that metaphor, note that cURL is a powerdrill with a complicated drill chuck that requires you to know it pretty well to actually change it (read: setting cURL options is a bit tedious, but allows for doing anything you want). – poke Jun 16 '12 at 16:09
  • 23
    `file_get_contents` allows also to set the context, which means you can set the header fields as you like. – velop Nov 03 '13 at 14:36
  • 4
    and as addition to @velop's comment, through the stream context it is also possible to send POST, PUT, authentication, headers, content, proxy, and much more with one file_get_contents request – Markus Köhler Jul 29 '15 at 14:53
  • @velop: Yes. And method, too. And redirects. And timeout... http://php.net/manual/en/context.http.php – Sz. Mar 28 '18 at 19:54
29

In addition to this, due to some recent website hacks we had to secure our sites more. In doing so, we discovered that file_get_contents failed to work, where curl still would work.

Not 100%, but I believe that this php.ini setting may have been blocking the file_get_contents request.

; Disable allow_url_fopen for security reasons
allow_url_fopen = 0

Either way, our code now works with curl.

vr_driver
  • 1,547
  • 23
  • 35
  • 9
    Yes, `file_get_contents` requires `allow_url_fopen` to be truthy. – Costa Nov 19 '13 at 01:40
  • 2
    Yes, many hosting companies are disabling `file_get_contents()` due to many exploits that are known to use the function. cURL is the function people should be using in code now. – frustratedtech Dec 20 '13 at 04:43
  • 15
    @frustratedtech What "exploits" are these? – rdlowrey Mar 02 '14 at 15:36
  • 3
    Hosting companies disable `allow_url_fopen` because they kind of mistake it for `allow_url_include`. `allow_url_fopen` and `file_get_contents` are fine to use. – fritzmg May 04 '15 at 10:42
  • @rdlowrey, http://curl.haxx.se/docs/vulnerabilities.html https://blog.cloudflare.com/inside-shellshock/ – vr_driver Jun 24 '15 at 08:18
  • 2
    @vr_driver those links have nothing to do with `file_get_contents()` – rdlowrey Jun 24 '15 at 15:16
  • Yes, hosting companies disable allow_url_fopen because of exploits. The typical use case of file_get_contents is to read a local file. But if you can find a way to override the filename and pass a URL instead, then you can read a REMOTE file instead (and it could be a file whose contents you control...) I understand the need to keep this box locked shut. file_get_contents should not have been given this magical power in the first place - it should have been a separate function. – jdhildeb Jul 02 '19 at 20:58
  • @jdhildeb it is not a "magical power", nor an obscure use case, as evidenced by "Example #1 Get and output the source of the homepage of a website", it is simply a wrapper for fopen(). if you can find a way to override the filename and pass a URL instead, you are either ignoring or in dire need of basic security practice – verbumSapienti Jul 07 '19 at 21:43
24

This is old topic but on my last test on one my API, cURL is faster and more stable. Sometimes file_get_contents on larger request need over 5 seconds when cURL need only from 1.4 to 1.9 seconds what is double faster.

I need to add one note on this that I just send GET and recive JSON content. If you setup cURL properly, you will have a great response. Just "tell" to cURL what you need to send and what you need to recive and that's it.

On your exampe I would like to do this setup:

$ch =  curl_init('http://api.bitly.com/v3/shorten?login=user&apiKey=key&longUrl=url');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
    curl_setopt($ch, CURLOPT_TIMEOUT, 3);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json'));
$result = curl_exec($ch);

This request will return data in 0.10 second max

Ivijan Stefan Stipić
  • 5,633
  • 5
  • 39
  • 74