file_get_contents 1 minute timeout for https?

By | December 11, 2017
Questions:

I’m having difficulty with PHP’s file_get_contents hanging for 60s when accessing certain resources over https.

I’m not sure whether it’s a client or server end issue.

On the client

Working on the command line:

$ URL="https://example.com/some/path"
$ wget "$URL" -O /dev/null -q # takes a few milliseconds
$ curl "$URL" >/dev/null      # takes a few milliseconds
$ php -r 'file_get_contents("'"$URL"'")' # takes 61s!

On the server

An line is written to the Apache (2.4) access log for the correct SSL vhost immediately, with a 200 (success) response. This is confusing a confusing timeline:

  • 0s php’s file_get_contents triggered on client
  • 0.2s server’s apache access log logs a successful (200).
  • ???who knows what is going on here???
  • 60.2s client receives the file.

Tested from Ubuntu 14.04 and Debian 8 clients. The resources in question are all on Debian 8 servers running Apache 2.4 with ITK worker and PHP 5.6. I’ve tried it with the firewall turned off (default ACCEPT policy), so it’s not that. Nb. the servers have IPv6 disabled, which could be related as I’ve noticed timeouts like this when something tries IPv6 first. But the hosts being accessed do not have AAAA records, and the apache logs show that (a) the SSL was established Ok and that (b) the request was valid and received.

Answers:

One possible answer: are you sure the client only receives the file after 60.2 seconds? If I remember correctly, file_get_contents() has a nasty habit of waiting for the remote connection to close before it considers the request completed. This means that if your server is using HTTP keep alive, which effectively keeps the connection for a period of time once all data transfer has completed, your application may appear to hang.

Does something like this help?

$context = stream_context_create(['http' => ['header' => 'Connection: close\r\n']]);
file_get_contents("https://example.com/some/path", false, $context);

NB: You may need to use ‘https’ for the key in that array; I don’t recall off the top of my head.

Questions:
Answers:

try to trace script
php -r 'file_get_contents("'"$URL"'")' & will run script in background and show script pid. And than strace -p %pid%

Questions:
Answers:

Thanks to the answers for pointing me deeper!

This seems to be a fault/quirk of using the ITK Apache MPM worker.

  • With that module this problem (file_get_contents not closing connection) exhibits itself.

  • Without this module the problem goes away.

It’s not the first bug I’ve found with that module since upgrading to Debian Jessie / Apache 2.4. I’ll try to report it.

Ah ha! I was right. It was a bug and there’s a fix released, currently in Debian jessie proposed updates.

Leave a Reply

Your email address will not be published. Required fields are marked *