HTTP_Request_Listener

HTTP_Request_Listener – attaching listeners to HTTP_Request operations

Introduction to HTTP_Request_Listener

HTTP_Request_Listener is an abstract class that can be extended to capture events and respond to them as they occur. Included with HTTP_Request is an example of a console-based progress bar. To implement this, the HTTP_Request_DownloadListener class is used, which uses the Console_ProgressBar package to display a download progress meter.

Example usage of HTTP_Request_Listener

In order to use a listener, it must attach to the specific HTTP_Request or HTTP_Response object that you want to monitor. The attach code is shown at the bottom of the example. As you can see, the event listener is propagated from the HTTP_Request object to any child HTTP_Response objects, and attaching only need happen to the first HTTP_Request object.

Download progress bar with HTTP_Request_Listener

<?php
/**
 * An example of Listener usage with HTTP_Request. This downloads and saves 
 * the file displaying the progress bar in the process.
 * 
 * Note two things:
 * 1) The file should be run in console, not in browser;
 * 2) You should turn output buffering OFF for this to work properly.
 */

require_once 'HTTP/Request.php';
require_once 
'HTTP/Request/Listener.php';
require_once 
'Console/ProgressBar.php';

PEAR::setErrorHandling(PEAR_ERROR_DIE);

set_time_limit(0);

class 
HTTP_Request_DownloadListener extends HTTP_Request_Listener
{
   
/**
    * Handle for the target file
    * @var int
    */
    
var $_fp;

   
/**
    * Console_ProgressBar intance used to display the indicator
    * @var object
    */
    
var $_bar;

   
/**
    * Name of the target file
    * @var string
    */
    
var $_target;

   
/**
    * Number of bytes received so far
    * @var int
    */
    
var $_size 0;

    function 
HTTP_Request_DownloadListener()
    {
        
$this->HTTP_Request_Listener();
    }

   
/**
    * Opens the target file
    * @param string Target file name
    * @throws PEAR_Error
    */
    
function setTarget($target)
    {
        
$this->_target $target;
        
$this->_fp = @fopen($target'wb');
        if (!
$this->_fp) {
            
PEAR::raiseError("Cannot open '{$target}'");
        }
    }

    function 
update(&$subject$event$data null)
    {
        switch (
$event) {
            case 
'sentRequest'
                
$this->_target basename($subject->_url->path);
                break;

            case 
'gotHeaders':
                if (isset(
$data['content-disposition']) &&
                    
preg_match('/filename="([^"]+)"/'$data['content-disposition'], $matches)) {

                    
$this->setTarget(basename($matches[1]));
                } else {
                    
$this->setTarget($this->_target);
                }
                
$this->_bar =& new Console_ProgressBar(
                    
'* ' $this->_target ' %fraction% KB [%bar%] %percent%''=>''-'
                    
79, (isset($data['content-length'])? round($data['content-length'] / 1024): 100)
                );
                
$this->_size 0;
                break;

            case 
'tick':
                
$this->_size += strlen($data);
                
$this->_bar->update(round($this->_size 1024));
                
fwrite($this->_fp$data);
                break;

            case 
'gotBody':
                
fclose($this->_fp);
                break;

            case 
'connect':
            case 
'disconnect':
                break;

            default:
                
PEAR::raiseError("Unhandled event '{$event}'");
        } 
// switch
    
}
}

// Try using any other package if you like, but choose the bigger ones
// to be able to see the progress bar
$url 'http://pear.php.net/get/HTML_QuickForm-stable';

$req =& new HTTP_Request($url);

$download =& new HTTP_Request_DownloadListener();
$req->attach($download);
$req->sendRequest(false);
?>

Events that can be caught

The HTTP_Request class sends these events:

  • connect - upon server connection, this event is sent

  • sentRequest - after the request was sent, this event is sent

  • disconnect - after server disconnect, this event is sent

The HTTP_Response class sends these events:

  • gotHeaders - this event is sent after receiving response headers (headers are passed in $data as an associative array)

  • tick - this event is sent on receiving a part of response body (the part is passed in $data as a string)

  • gzTick - this event is sent on receiving a part of response body that is gzip-compressed (the part is passed in $data as a string)

  • gotBody - this event is sent on after receiving the complete response body (the decoded body is passed as a string in $data if it was gzipped)