Scaricare il contenuto di una pagina con Zend_Http_Client

weppos January 9th, 2008

Zend_Http_Client è un componente di Zend Framework estremamente importante, alla base di tutti i componenti di Zend_Service, ma non solo.
Come rivela il nome, si tratta di un Client HTTP scritto completamente in PHP.

Molti di voi conosceranno cURL, anch’esso un HTTP Client disponibile per PHP.
Sebbene sia molto diffuso, non tutte le configurazioni di PHP prevedono questa libreria di default ed alcune impostazioni, come safe mode, potrebbero limitarne l’uso. Inoltre, è opinione diffusa che il suo utilizzo non sia troppo “elegante”.

Zend_Http_Client supporta quasi tutte le funzionalità di cURL e molti altri client HTTP: autenticazione, Cookie, CookieJar, redirect ed offre un completo set di metodi per analizzare la risposta HTTP ed il suo contenuto, il tutto con una sintassi object oriented.
Zend_Http_Client fa largo uso del componente Zend_Uri, in particolare della sua sottoclasse specifica Zend_Uri_Http, per manipolare le URL.

Nell’esempio seguente vediamo come recuperare un semplice contenuto di una pagina tramite una richiesta HTTP GET, stamparne gli header ed il contenuto se la risposta va a buon fine.
Per complicare leggermente lo script, l’URL viene recuperato da una form e validato sfruttando uno degli approcci già descritti nell’articolo Validare un URL in PHP con Zend_Uri.

<?php

// includi la libreria
require_once 'Zend/Http/Client.php';

if (isset($_GET['url'])) {
    try {
        // esegui il parsing dell'URL
        $uri = Zend_Uri::factory(trim($_GET['url']));

        // useragent personalizzata
        $useragent = 'TestClient/1.0';

        // crea un nuovo client HTTP ed imposta le configurazioni
        $httpClient = new Zend_Http_Client();
        $httpClient->setConfig(array('useragent' => $useragent));
        $httpClient->setUri($uri);

        // invia la richiesta HTTP
        $response = $httpClient->request();

        // controlla la risposta
        if (!$response->isSuccessful()) {
            // genera un'eccezione in caso di status HTTP non valido
            throw new Zend_Http_Client_Exception('HTTP ' . $response->getStatus() . ' - ' . $response->getMessage());
        }

        echo "<h1>" . $uri . "</h1>";
        echo "<h2>Headers:</h2>";
        echo "<pre>";
        foreach($response->getHeaders() as $name => $value) {
            echo "$name: $value\n";
        }
        echo "</pre>";

        // stampa il contenuto della pagina in una textaread
        echo "<h2>Content:</h2>";
        echo "<textarea cols=\"80\" rows=\"80\">" . $response->getBody() . "</textarea>";

    } catch(Zend_Exception $e) {
        echo "<h1>Error: " . $e->getMessage() . "</h1>";
    }
}

?>
<form>
<p>
<input type="text" name="url" value="http://" />
<input type="submit" name="submit" value="fetch!" />
</p>
</form>

Lo script è molto essenziale e non è stato sviluppato tenendo in cosiderazione alcun principio alla base del design pattern MVC.
L’implementazione di un progetto MVC è, al momento, oltre lo scopo di questo semplice script.

Il codice è commentato a sufficienza, tuttavia ci sono alcuni aspetti che può essere utile commentare insieme.

Uso delle eccezioni in un codice procedurale

Innanzi tutto da notare l’uso di un unico blocco try...catch per gestire a monte qualsiasi eccezione generata dai componenti di Zend.
Sfruttando le eccezioni di PHP 5 è possibile evitare noiosi e ripetitivi controlli e rendere il codice più fluido, anche se scritto in modo procedurale.
Inoltre, possiamo sfruttare il blocco per lanciare noi stessi un’eccezione in caso sia necessario interrompere l’elaborazione (nel nostro caso se una risposta contiene uno status HTTP diverso da 200 o 304).

Le seguenti esecuzioni parte dello Zend Framework possono generare un’eccezione:

  1. Zend_Uri::factory(trim($_GET['url'])) in caso l’URL fornito non sia valido
  2. $response = $httpClient->request(); in caso la richiesta HTTP non vada a buon fine, ad esempio se la connessione internet non è disponibile

Poiché qualsiasi eccezione lanciata da un componente dello Zend Framework estende Zend_Exception, è sufficiente indicare a PHP di catturare una qualsiasi eccezione figlia di questa classe.

Impostazioni personalizzate

Zend_Client_Http consente di inviare intestazioni (header) personalizzate.
Tra gli header, quello senz’altro più famoso è la stringa User Agent che spesso indica univocamente il tipo di client in uso: browser come Mozilla Firefox o Internet Explorer, crawler come Yahoo! Slurp o Googlebot…

Nel nostro caso abbiamo scelto di identificare il nostro client con la stringa 'TestClient/1.0'.
Nei log del server le nostre richieste figureranno quindi associate a questa user agent.

Non è MVC!

Sebbene Zend Framework sia un framework MVC, come già anticipato, questo argomento è oltre allo scopo di questo script e si è adottata una soluzione procedurale per rendere il tutorial più sintetico ed immediato.

Non sempre l’architettura MVC riflette al meglio le esigenze di chi sviluppa… questo era uno di quei casi! ;)

Trackback URI | Comments RSS

Leave a Reply