File_get_contents a timeout

V případě, že je potřeba stáhnout obsah z nějaké cizí stránky, hodí se k tomu PHP funkce file_get_contents.

Čekání na odpověď

Problém tohoto postupu nastane ve chvíli, kdy cílová stránka nebude odpovídat. V takovém případě se PHP bude marně snažit až do vyčerpání časového limitu (Maximum execution time), což může být třeba 30 vteřin.

Většinou to ale je tak, že když stránka nevrátí obsah do několika stovek milisekund, nejspíš ho nevrátí vůbec (má výpadek a podobně).

Proto u akcí, které vyvolává běžný návštěvník, je dobré nastavit časový limit. Běžný uživatel často nebude ochotný čekat déle než řádově několik vteřin.

Doporučený postup

Získávání obsahu, které by mohlo blokovat vykreslení stránky, nastavit s nízkým časovým limitem a v případě neúspěchu zkusit data donačíst později AJAXem.

A nebo použít cache.

Nastavení timeoutu

$context = stream_context_create(
  array('http' =>
    array(
      'timeout' => 1 // Timeout ve vteřinách
    )
  )
);
$soubor = @file_get_contents(
  "http://example.com", 
  false, 
  $context
);

Timeout se funkci file_get_contents dá nastavit přes tzv. context, jenž se předá jako třetí argument.

Zajímavé chování má časová jednotka pro timeout, která v praxi trvá dvakrát víc sekund, než se nastaví. Uvedená ukázka má tedy skutečný timeout 2 sekundy.

V případě, že časový limit znemožní stažení stránky, vrátí file_get_contents varování:

Warning: file_get_contents(…): 
  failed to open stream: HTTP request failed!

To je proto potlačeno zavináčem. V případě chyby bude v proměnné $soubor hodnota false (jinak získaný obsah).

HTTPS

Přestože se v poli při vytváření kontextu (stream_context_create) píše http, získání obsahu včetně nastavení limitu může fungovat i na HTTPS.

cURL

S využitím cURL se timeout nastavuje takto:

function curlObsah($url) {
  $c = curl_init();
  curl_setopt($c, CURLOPT_TIMEOUT, 1);
  curl_setopt($c, CURLOPT_URL, $url);
  $result = curl_exec($c);
  curl_close($c);
  return $result;
}

Existuje i nastavení CURLOPT_TIMEOUT_MS pro zadávání času v milisekundách. Nicméně často nižší timeout než 1 vteřinu není možné nastavit (nastavení v milisekundách by mělo fungovat od cURL 7.16.2 – od PHP 5.2.3).

Test obou postupů je na GitHubu.

To je všechno. Líbil se vám článek a chcete se dozvědět, až vyjde další?

Sledujte:

 

Připomínky mi pište do komentářů ↓

Stažení cizí stránky

Získání obsahu cizí stránky

Jak v PHP a JavaScriptu získat obsah z cizí webové stránky.

Parsování HTML v PHP

Parsování HTML v PHP

Jak v PHP parsovat HTML stránku a získat z ní potřebná data.

Cacheování obsahu z cizí stránky

Cacheování obsahu cizí stránky

Jak cacheovat výsledky obsahu staženého z cizí stránky.

Získání obsahu stránky přes oEmbed

Získání obsahu stránky přes oEmbed

Formát oEmbed slouží k pohodlnému získání obsahu stránky bez nutnosti jejího parsování.

PHP proxy skript

PHP proxy skript na 50 řádků

Hotový PHP skript umožňující zobrazit web prostřednictvím jiné IP adresy.

Komentáře