HTTP_Client
[ class tree: HTTP_Client ] [ index: HTTP_Client ] [ all elements ]

Source for file Client.php

Documentation is available at Client.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2003 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 3.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available through the world-wide-web at                              |
  11. // | http://www.php.net/license/3_0.txt.                                  |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Author: Alexey Borzov <avb@php.net>                                  |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: Client.php,v 1.4 2004/03/23 13:35:37 avb Exp $
  20.  
  21. require_once 'HTTP/Request.php';
  22. require_once 'HTTP/Client/CookieManager.php';
  23.  
  24. /**
  25.  * A simple HTTP client class.
  26.  * 
  27.  * The class wraps around HTTP_Request providing a higher-level
  28.  * API for performing multiple HTTP requests
  29.  * 
  30.  * @package HTTP_Client
  31.  * @author Alexey Borzov <avb@php.net>
  32.  * @version $Revision: 1.4 $
  33.  */
  34. {
  35.    /**
  36.     * An HTTP_Client_CookieManager instance
  37.     * @var object 
  38.     */
  39.     var $_cookieManager;
  40.  
  41.    /**
  42.     * Received HTTP responses
  43.     * @var array 
  44.     */
  45.     var $_responses;
  46.  
  47.    /**
  48.     * Default headers to send on every request
  49.     * @var array 
  50.     */
  51.     var $_defaultHeaders = array();
  52.  
  53.    /**
  54.     * Default parameters for HTTP_Request's constructor
  55.     * @var array 
  56.     */
  57.     var $_defaultRequestParams = array();
  58.  
  59.    /**
  60.     * How many redirects were done
  61.     * @var integer 
  62.     */
  63.     var $_redirectCount = 0;
  64.  
  65.    /**
  66.     * Maximum allowed redirects
  67.     * @var integer 
  68.     */
  69.     var $_maxRedirects = 5;
  70.  
  71.    /**
  72.     * Listeners attached to the client
  73.     * @var array 
  74.     */
  75.     var $_listeners = array();
  76.  
  77.    /**
  78.     * Whether the listener should be propagated to Request objects
  79.     * @var array 
  80.     */
  81.     var $_propagate = array();
  82.  
  83.    /**
  84.     * Whether to keep all the responses or just the most recent one
  85.     * @var boolean 
  86.     */
  87.     var $_isHistoryEnabled = true;
  88.  
  89.    /**
  90.     * Constructor
  91.     * 
  92.     * @access   public
  93.     * @param    array   Parameters to pass to HTTP_Request's constructor
  94.     * @param    array   Default headers to send on every request
  95.     */
  96.     function HTTP_Client($defaultRequestParams = null$defaultHeaders = null)
  97.     {
  98.         $this->_cookieManager =new HTTP_Client_CookieManager();
  99.         if (isset($defaultHeaders)) {
  100.             $this->setDefaultHeader($defaultHeaders);
  101.         }
  102.         if (isset($defaultRequestParams)) {
  103.             $this->setRequestParameter($defaultRequestParams);
  104.         }
  105.     }
  106.  
  107.  
  108.    /**
  109.     * Sets the maximum redirects that will be processed.
  110.     * 
  111.     * Setting this to 0 disables redirect processing. If not 0 and the
  112.     * number of redirects in a request is bigger than this number, then an
  113.     * error will be raised.
  114.     * 
  115.     * @access   public
  116.     * @param    int     Max number of redirects to process
  117.     */
  118.     function setMaxRedirects($value)
  119.     {
  120.         $this->_maxRedirects $value;
  121.     }
  122.  
  123.  
  124.    /**
  125.     * Sets whether to keep all the responses or just the most recent one
  126.     *
  127.     * @access public
  128.     * @param  bool      Whether to enable history
  129.     */
  130.     function enableHistory($enable)
  131.     {
  132.         $this->_isHistoryEnabled = (bool)$enable;
  133.     }
  134.  
  135.    /**
  136.     * Creates a HTTP_Request objects, applying all the necessary defaults
  137.     *
  138.     * @param    string   URL
  139.     * @param    integer  Method, constants are defined in HTTP_Request
  140.     * @access   private
  141.     * @return   object   HTTP_Request object with all defaults applied
  142.     */
  143.     function &_createRequest($url$method = HTTP_REQUEST_METHOD_GET)
  144.     {
  145.         $req =new HTTP_Request($url$this->_defaultRequestParams);
  146.         $req->setMethod($method);
  147.         foreach ($this->_defaultHeaders as $name => $value{
  148.             $req->addHeader($name$value);
  149.         }
  150.         $this->_cookieManager->passCookies($req);
  151.         foreach ($this->_propagate as $id => $propagate{
  152.             if ($propagate{
  153.                 $req->attach($this->_listeners[$id]);
  154.             }
  155.         }
  156.         return $req;
  157.     }
  158.     
  159.  
  160.    /**
  161.     * Sends a 'HEAD' HTTP request
  162.     *
  163.     * @param    string  URL
  164.     * @access   public
  165.     * @return   integer HTTP response code
  166.     * @throws   PEAR_Error
  167.     */
  168.     function head($url)
  169.     {
  170.         $request =$this->_createRequest($urlHTTP_REQUEST_METHOD_HEAD);
  171.         return $this->_performRequest($request);
  172.     }
  173.    
  174.  
  175.    /**
  176.     * Sends a 'GET' HTTP request
  177.     * 
  178.     * @param    string  URL
  179.     * @param    mixed   additional data to send
  180.     * @param    boolean Whether the data is already urlencoded
  181.     * @access   public
  182.     * @return   integer HTTP response code
  183.     * @throws   PEAR_Error
  184.     */
  185.     function get($url$data = null$preEncoded = false)
  186.     {
  187.         $request =$this->_createRequest($url);
  188.         if (is_array($data)) {
  189.             foreach ($data as $name => $value{
  190.                 $request->addQueryString($name$value$preEncoded);
  191.             }
  192.         elseif (isset($data)) {
  193.             $request->addRawQueryString($data$preEncoded);
  194.         }
  195.         return $this->_performRequest($request);
  196.     }
  197.  
  198.  
  199.    /**
  200.     * Sends a 'POST' HTTP request
  201.     *
  202.     * @param    string  URL
  203.     * @param    mixed   Data to send
  204.     * @param    boolean Whether the data is already urlencoded
  205.     * @param    array   Files to upload. Elements of the array should have the form:
  206.     *                    array(name, filename(s)[, content type]), see HTTP_Request::addFile()
  207.     * @access   public
  208.     * @return   integer HTTP response code
  209.     * @throws   PEAR_Error
  210.     */
  211.     function post($url$data$preEncoded = false$files = array())
  212.     {
  213.         $request =$this->_createRequest($urlHTTP_REQUEST_METHOD_POST);
  214.         if (is_array($data)) {
  215.             foreach ($data as $name => $value{
  216.                 $request->addPostData($name$value$preEncoded);
  217.             }
  218.         else {
  219.             $request->addRawPostData($data$preEncoded);
  220.         }
  221.         foreach ($files as $fileData{
  222.             $res call_user_func_array(array(&$request'addFile')$fileData);
  223.             if (PEAR::isError($res)) {
  224.                 return $res;
  225.             }
  226.         }
  227.         return $this->_performRequest($request);
  228.     }
  229.  
  230.  
  231.    /**
  232.     * Sets default header(s) for HTTP requests
  233.     *
  234.     * @param    mixed   header name or array ('header name' => 'header value')
  235.     * @param    string  header value if $name is not an array
  236.     * @access   public
  237.     */
  238.     function setDefaultHeader($name$value = null)
  239.     {
  240.         if (is_array($name)) {
  241.             $this->_defaultHeaders array_merge($this->_defaultHeaders$name);
  242.         else {
  243.             $this->_defaultHeaders[$name$value;
  244.         }
  245.     }
  246.  
  247.  
  248.    /**
  249.     * Sets parameter(s) for HTTP requests
  250.     *
  251.     * @param    mixed   parameter name or array ('parameter name' => 'parameter value')
  252.     * @param    string  parameter value if $name is not an array
  253.     * @access   public
  254.     */
  255.     function setRequestParameter($name$value = null)
  256.     {
  257.         if (is_array($name)) {
  258.             $this->_defaultRequestParams array_merge($this->_defaultRequestParams$name);
  259.         else {
  260.             $this->_defaultRequestParams[$name$value;
  261.         }
  262.     }
  263.       
  264.  
  265.    /**
  266.     * Performs a request, processes redirects
  267.     *
  268.     * @param    object  HTTP_Request object
  269.     * @access   private
  270.     * @return   integer HTTP response code
  271.     * @throws   PEAR_Error
  272.     */
  273.     function _performRequest(&$request)
  274.     {
  275.         // If this is not a redirect, notify the listeners of new request
  276.         if (0 == $this->_redirectCount{
  277.             $this->_notify('request'$request->_url->getUrl());
  278.         }
  279.         if (PEAR::isError($err $request->sendRequest())) {
  280.             return $err;
  281.         }
  282.         $this->_pushResponse($request);
  283.  
  284.         $code $request->getResponseCode();
  285.         if ($this->_maxRedirects > 0 && in_array($codearray(300301302303307))) {
  286.             if (++$this->_redirectCount $this->_maxRedirects{
  287.                 return PEAR::raiseError('Too many redirects');
  288.             }
  289.             $location $request->getResponseHeader('Location');
  290.             if ('' == $location{
  291.                 return PEAR::raiseError("No 'Location' field on redirect");
  292.             }
  293.             $url $this->_redirectUrl($request->_url$location);
  294.             // Notify of redirection
  295.             $this->_notify('httpRedirect'$url);
  296.             // we access the private properties directly, as there are no accessors for them
  297.             switch ($request->_method{
  298.                 case HTTP_REQUEST_METHOD_POST: 
  299.                     if (302 == $code || 303 == $code{
  300.                         return $this->get($url);
  301.                     else {
  302.                         $postFiles = array();
  303.                         foreach ($request->_postFiles as $name => $data{
  304.                             $postFiles[= array($name$data['name']$data['type']);
  305.                         }
  306.                         return $this->post($url$request->_postDatatrue$postFiles);
  307.                     }
  308.                 case HTTP_REQUEST_METHOD_HEAD:
  309.                     return (303 == $code$this->get($url)$this->head($url));
  310.                 case HTTP_REQUEST_METHOD_GET: 
  311.                 default:
  312.                     return $this->get($url);
  313.             // switch
  314.  
  315.         else {
  316.             $this->_redirectCount = 0;
  317.             if (400 >= $code{
  318.                 $this->_notify('httpSuccess');
  319.                 $this->setDefaultHeader('Referer'$request->_url->getUrl());
  320.                 // some result processing should go here
  321.             else {
  322.                 $this->_notify('httpError');
  323.             }
  324.         }
  325.         return $code;
  326.     }
  327.  
  328.  
  329.    /**
  330.     * Returns the most recent HTTP response
  331.     * 
  332.     * @access public
  333.     * @return array 
  334.     */
  335.     function &currentResponse()
  336.     {
  337.         return $this->_responses[count($this->_responses- 1];
  338.     }
  339.  
  340.  
  341.    /**
  342.     * Saves the server's response to responses list
  343.     *
  344.     * @param    object  HTTP_Request object, with request already sent
  345.     * @access   private
  346.     */
  347.     function _pushResponse(&$request)
  348.     {
  349.         $this->_cookieManager->updateCookies($request);
  350.         $idx   $this->_isHistoryEnabledcount($this->_responses): 0;
  351.         $this->_responses[$idx= array(
  352.             'code'    => $request->getResponseCode(),
  353.             'headers' => $request->getResponseHeader(),
  354.             'body'    => $request->getResponseBody()
  355.         );
  356.     }
  357.  
  358.  
  359.    /**
  360.     * Clears object's internal properties
  361.     *
  362.     * @access public
  363.     */
  364.     function reset()
  365.     {
  366.         $this->_cookieManager->reset();
  367.         $this->_responses            = array();
  368.         $this->_defaultHeaders       = array();
  369.         $this->_defaultRequestParams = array();
  370.     }
  371.  
  372.  
  373.    /**
  374.     * Adds a Listener to the list of listeners that are notified of
  375.     * the object's events
  376.     * 
  377.     * @param    object   HTTP_Request_Listener instance to attach
  378.     * @param    boolean  Whether the listener should be attached to the
  379.     *                     created HTTP_Request objects
  380.     * @return   boolean  whether the listener was successfully attached
  381.     * @access   public
  382.     */
  383.     function attach(&$listener$propagate = false)
  384.     {
  385.         if (!is_a($listener'HTTP_Request_Listener')) {
  386.             return false;
  387.         }
  388.         $this->_listeners[$listener->getId()=$listener;
  389.         $this->_propagate[$listener->getId()=  $propagate;
  390.         return true;
  391.     }
  392.  
  393.  
  394.    /**
  395.     * Removes a Listener from the list of listeners
  396.     * 
  397.     * @param    object   HTTP_Request_Listener instance to detach
  398.     * @return   boolean  whether the listener was successfully detached
  399.     * @access   public
  400.     */
  401.     function detach(&$listener)
  402.     {
  403.         if (!is_a($listener'HTTP_Request_Listener'|| 
  404.             !isset($this->_listeners[$listener->getId()])) {
  405.             return false;
  406.         }
  407.         unset($this->_listeners[$listener->getId()]$this->_propagate[$listener->getId()]);
  408.         return true;
  409.     }
  410.  
  411.  
  412.    /**
  413.     * Notifies all registered listeners of an event.
  414.     * 
  415.     * Currently available events are:
  416.     * 'request': sent on HTTP request that is not a redirect
  417.     * 'httpSuccess': sent when we receive a successfull 2xx response
  418.     * 'httpRedirect': sent when we receive a redirection response
  419.     * 'httpError': sent on 4xx, 5xx response
  420.     * 
  421.     * @param    string  Event name
  422.     * @param    mixed   Additional data
  423.     * @access   private
  424.     */
  425.     function _notify($event$data = null)
  426.     {
  427.         foreach (array_keys($this->_listenersas $id{
  428.             $this->_listeners[$id]->update($this$event$data);
  429.         }
  430.     }
  431.  
  432.  
  433.    /**
  434.     * Calculates the absolute URL of a redirect
  435.     *  
  436.     * @param    object  Net_Url object containing the request URL
  437.     * @param    string  Value of the 'Location' response header
  438.     * @return   string  Absolute URL we are being redirected to
  439.     * @access   private
  440.     */
  441.     function _redirectUrl($url$location)
  442.     {
  443.         if (preg_match('!^https?://!i'$location)) {
  444.             return $location;
  445.         else {
  446.             if ('/' == $location{0}{
  447.                 $url->path = Net_URL::resolvePath($location);
  448.             elseif('/' == substr($url->path-1)) {
  449.                 $url->path = Net_URL::resolvePath($url->path . $location);
  450.             else {
  451.                 $dirname (DIRECTORY_SEPARATOR == dirname($url->path)'/'dirname($url->path));
  452.                 $url->path = Net_URL::resolvePath($dirname '/' $location);
  453.             }
  454.             $url->querystring = array();
  455.             $url->anchor      = '';
  456.             return $url->getUrl();
  457.         }
  458.     }
  459. }
  460. ?>

Documentation generated on Mon, 11 Mar 2019 10:17:28 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.