【PHPsocket編程專題(實戰篇②)】兼容 Curl/Socket/Stream 的 HTTP 操做類[轉]

<?php
/************************************************************
 *  描述:HTTP操做類
 *  做者:heiyeluren
 *  建立:2009/12/13 04:43
 *  修改:2009/12/16 10:30  實現基本HTTP各類接口操做支持
 ************************************************************/

/**
 * HTTP功能工廠方法類
 * 調用示例代碼:
 * try {
 * $http = Http::factory('http://www.baidu.com', Http::TYPE_SOCK );
 * echo $http->get();
 * $http = Http::factory('http://127.0.0.1/test/i.php', Http::TYPE_SOCK );
 * echo $http->post('', array('user'=>'咱們', 'nick'=>'ASSADF@#!32812989+-239%ASDF'), '', array('aa'=>'bb', 'cc'=>'dd'));
 * } catch (Exception $e) {
 * echo $e->getMessage();
 * }
 */
class Http{
  /**
   * @var 使用 CURL
   */
  const TYPE_CURL = 1;
  /**
   * @var 使用 Socket
   */
  const TYPE_SOCK = 2;
  /**
   * @var 使用 Stream
   */
  const TYPE_STREAM = 3;

  /**
   * 保證對象不被clone
   */
  private function __clone(){
  }

  /**
   * 構造函數
   */
  private function __construct(){
  }

  /**
   * HTTP工廠操做方法
   * @param string $url 須要訪問的URL
   * @param int $type 須要使用的HTTP類
   * @return object
   */
  public static function factory($url = '' , $type = self::TYPE_SOCK){
    if ($type == '') {
      $type = self::TYPE_SOCK;
    }
    switch ($type) {
      case self::TYPE_CURL :
        if (!function_exists('curl_init')) {
          throw new Exception(__CLASS__ . " PHP CURL extension not install");
        }
        $obj = Http_Curl::getInstance($url);
        break;
      case self::TYPE_SOCK :
        if (!function_exists('fsockopen')) {
          throw new Exception(__CLASS__ . " PHP function fsockopen() not support");
        }
        $obj = Http_Sock::getInstance($url);
        break;
      case self::TYPE_STREAM :
        if (!function_exists('stream_context_create')) {
          throw new Exception(__CLASS__ . " PHP Stream extension not install");
        }
        $obj = Http_Stream::getInstance($url);
        break;
      default:
        throw new Exception("http access type $type not support");
    }
    return $obj;
  }

  /**
   * 生成一個供Cookie或HTTP GET Query的字符串
   * @param array $data 須要生產的數據數組,必須是 Name => Value 結構
   * @param string $sep 兩個變量值之間分割的字符,缺省是 &
   * @return string 返回生成好的Cookie查詢字符串
   */
  public static function makeQuery($data , $sep = '&'){
    $encoded = '';
    while (list($k , $v) = each($data)) {
      $encoded .= ($encoded ? "$sep" : "");
      $encoded .= rawurlencode($k) . "=" . rawurlencode($v);
    }
    return $encoded;
  }
}

/**
 * 使用CURL 做爲核心操做的HTTP訪問類
 * @desc CURL 以穩定、高效、移植性強做爲很重要的HTTP協議訪問客戶端,必須在PHP中安裝 CURL 擴展才能使用本功能
 */
class Http_Curl{
  /**
   * @var object 對象單例
   */
  static $_instance = NULL;
  /**
   * @var string 須要發送的cookie信息
   */
  private $cookies = '';
  /**
   * @var array 須要發送的頭信息
   */
  private $header = array();
  /**
   * @var string 須要訪問的URL地址
   */
  private $uri = '';
  /**
   * @var array 須要發送的數據
   */
  private $vars = array();

  /**
   * 構造函數
   * @param string $configFile 配置文件路徑
   */
  private function __construct($url){
    $this->uri = $url;
  }

  /**
   * 保證對象不被clone
   */
  private function __clone(){
  }

  /**
   * 獲取對象惟一實例
   * @param string $configFile 配置文件路徑
   * @return object 返回本對象實例
   */
  public static function getInstance($url = ''){
    if (!(self::$_instance instanceof self)) {
      self::$_instance = new self($url);
    }
    return self::$_instance;
  }

  /**
   * 設置須要發送的HTTP頭信息
   * @param array /string 須要設置的頭信息,能夠是一個 相似 array('Host: example.com', 'Accept-Language: zh-cn') 的頭信息數組
   *       或單一的一條相似於 'Host: example.com' 頭信息字符串
   * @return void
   */
  public function setHeader($header){
    if (emptyempty($header)) {
      return;
    }
    if (is_array($header)) {
      foreach ($header as $k => $v) {
        $this->header[] = is_numeric($k) ? trim($v) : (trim($k) . ": " . trim($v));
      }
    } elseif (is_string($header)) {
      $this->header[] = $header;
    }
  }

  /**
   * 設置Cookie頭信息
   * 注意:本函數只能調用一次,下次調用會覆蓋上一次的設置
   * @param string /array 須要設置的Cookie信息,一個相似於 'name1=value1&name2=value2' 的Cookie字符串信息,
   *         或者是一個 array('name1'=>'value1', 'name2'=>'value2') 的一維數組
   * @return void
   */
  public function setCookie($cookie){
    if (emptyempty($cookie)) {
      return;
    }
    if (is_array($cookie)) {
      $this->cookies = Http::makeQuery($cookie , ';');
    } elseif (is_string($cookie)) {
      $this->cookies = $cookie;
    }
  }

  /**
   * 設置要發送的數據信息
   * 注意:本函數只能調用一次,下次調用會覆蓋上一次的設置
   * @param array 設置須要發送的數據信息,一個相似於 array('name1'=>'value1', 'name2'=>'value2') 的一維數組
   * @return void
   */
  public function setVar($vars){
    if (emptyempty($vars)) {
      return;
    }
    if (is_array($vars)) {
      $this->vars = $vars;
    }
  }

  /**
   * 設置要請求的URL地址
   * @param string $url 須要設置的URL地址
   * @return void
   */
  public function setUrl($url){
    if ($url != '') {
      $this->uri = $url;
    }
  }

  /**
   * 發送HTTP GET請求
   * @param string $url 若是初始化對象的時候沒有設置或者要設置不一樣的訪問URL,能夠傳本參數
   * @param array $vars 須要單獨返送的GET變量
   * @param array /string 須要設置的頭信息,能夠是一個 相似 array('Host: example.com', 'Accept-Language: zh-cn') 的頭信息數組
   *         或單一的一條相似於 'Host: example.com' 頭信息字符串
   * @param string /array 須要設置的Cookie信息,一個相似於 'name1=value1&name2=value2' 的Cookie字符串信息,
   *         或者是一個 array('name1'=>'value1', 'name2'=>'value2') 的一維數組
   * @param int $timeout 鏈接對方服務器訪問超時時間,單位爲秒
   * @param array $options 當前操做類一些特殊的屬性設置
   * @return unknown
   */
  public function get($url = '' , $vars = array() , $header = array() , $cookie = '' , $timeout = 5 , $options = array()){
    $this->setUrl($url);
    $this->setHeader($header);
    $this->setCookie($cookie);
    $this->setVar($vars);
    return $this->send('GET' , $timeout);
  }

  /**
   * 發送HTTP POST請求
   * @param string $url 若是初始化對象的時候沒有設置或者要設置不一樣的訪問URL,能夠傳本參數
   * @param array $vars 須要單獨返送的GET變量
   * @param array /string 須要設置的頭信息,能夠是一個 相似 array('Host: example.com', 'Accept-Language: zh-cn') 的頭信息數組
   *         或單一的一條相似於 'Host: example.com' 頭信息字符串
   * @param string /array 須要設置的Cookie信息,一個相似於 'name1=value1&name2=value2' 的Cookie字符串信息,
   *         或者是一個 array('name1'=>'value1', 'name2'=>'value2') 的一維數組
   * @param int $timeout 鏈接對方服務器訪問超時時間,單位爲秒
   * @param array $options 當前操做類一些特殊的屬性設置
   * @return unknown
   */
  public function post($url = '' , $vars = array() , $header = array() , $cookie = '' , $timeout = 5 , $options = array()){
    $this->setUrl($url);
    $this->setHeader($header);
    $this->setCookie($cookie);
    $this->setVar($vars);
    return $this->send('POST' , $timeout);
  }

  /**
   * 發送HTTP請求核心函數
   * @param string $method 使用GET仍是POST方式訪問
   * @param array $vars 須要另外附加發送的GET/POST數據
   * @param int $timeout 鏈接對方服務器訪問超時時間,單位爲秒
   * @param array $options 當前操做類一些特殊的屬性設置
   * @return string 返回服務器端讀取的返回數據
   */
  public function send($method = 'GET' , $timeout = 5 , $options = array()){
    //處理參數是否爲空   
    if ($this->uri == '') {
      throw new Exception(__CLASS__ . ": Access url is empty");
    }
    //初始化CURL   
    $ch = curl_init();
    curl_setopt($ch , CURLOPT_HEADER , 0);
    curl_setopt($ch , CURLOPT_FOLLOWLOCATION , 1);
    curl_setopt($ch , CURLOPT_RETURNTRANSFER , 1);
    curl_setopt($ch , CURLOPT_TIMEOUT , $timeout);
    //設置特殊屬性   
    if (!emptyempty($options)) {
      curl_setopt_array($ch , $options);
    }
    //處理GET請求參數   
    if ($method == 'GET' && !emptyempty($this->vars)) {
      $query = Http::makeQuery($this->vars);
      $parse = parse_url($this->uri);
      $sep = isset($parse['query']) ? '&' : '?';
      $this->uri .= $sep . $query;
    }
    //處理POST請求數據   
    if ($method == 'POST') {
      curl_setopt($ch , CURLOPT_POST , 1);
      curl_setopt($ch , CURLOPT_POSTFIELDS , $this->vars);
    }
    //設置cookie信息   
    if (!emptyempty($this->cookies)) {
      curl_setopt($ch , CURLOPT_COOKIE , $this->cookies);
    }
    //設置HTTP缺省頭   
    if (emptyempty($this->header)) {
      $this->header = array('User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1)' , //'Accept-Language: zh-cn',             
        //'Cache-Control: no-cache',   
      );
    }
    curl_setopt($ch , CURLOPT_HTTPHEADER , $this->header);
    //發送請求讀取輸數據   
    curl_setopt($ch , CURLOPT_URL , $this->uri);
    $data = curl_exec($ch);
    if (($err = curl_error($ch))) {
      curl_close($ch);
      throw new  Exception(__CLASS__ . " error: " . $err);
    }
    curl_close($ch);
    return $data;
  }
}

/**
 * 使用 Socket操做(fsockopen) 做爲核心操做的HTTP訪問接口
 * @desc Network/fsockopen 是PHP內置的一個Sokcet網絡訪問接口,必須安裝/打開 fsockopen 函數本類才能工做,
 *    同時確保其餘相關網絡環境和配置是正確的
 */
class Http_Sock{
  /**
   * @var object 對象單例
   */
  static $_instance = NULL;
  /**
   * @var string 須要發送的cookie信息
   */
  private $cookies = '';
  /**
   * @var array 須要發送的頭信息
   */
  private $header = array();
  /**
   * @var string 須要訪問的URL地址
   */
  private $uri = '';
  /**
   * @var array 須要發送的數據
   */
  private $vars = array();

  /**
   * 構造函數
   * @param string $configFile 配置文件路徑
   */
  private function __construct($url){
    $this->uri = $url;
  }

  /**
   * 保證對象不被clone
   */
  private function __clone(){
  }

  /**
   * 獲取對象惟一實例
   * @param string $configFile 配置文件路徑
   * @return object 返回本對象實例
   */
  public static function getInstance($url = ''){
    if (!(self::$_instance instanceof self)) {
      self::$_instance = new self($url);
    }
    return self::$_instance;
  }

  /**
   * 設置須要發送的HTTP頭信息
   * @param array /string 須要設置的頭信息,能夠是一個 相似 array('Host: example.com', 'Accept-Language: zh-cn') 的頭信息數組
   *       或單一的一條相似於 'Host: example.com' 頭信息字符串
   * @return void
   */
  public function setHeader($header){
    if (emptyempty($header)) {
      return;
    }
    if (is_array($header)) {
      foreach ($header as $k => $v) {
        $this->header[] = is_numeric($k) ? trim($v) : (trim($k) . ": " . trim($v));
      }
    } elseif (is_string($header)) {
      $this->header[] = $header;
    }
  }

  /**
   * 設置Cookie頭信息
   * 注意:本函數只能調用一次,下次調用會覆蓋上一次的設置
   * @param string /array 須要設置的Cookie信息,一個相似於 'name1=value1&name2=value2' 的Cookie字符串信息,
   *         或者是一個 array('name1'=>'value1', 'name2'=>'value2') 的一維數組
   * @return void
   */
  public function setCookie($cookie){
    if (emptyempty($cookie)) {
      return;
    }
    if (is_array($cookie)) {
      $this->cookies = Http::makeQuery($cookie , ';');
    } elseif (is_string($cookie)) {
      $this->cookies = $cookie;
    }
  }

  /**
   * 設置要發送的數據信息
   * 注意:本函數只能調用一次,下次調用會覆蓋上一次的設置
   * @param array 設置須要發送的數據信息,一個相似於 array('name1'=>'value1', 'name2'=>'value2') 的一維數組
   * @return void
   */
  public function setVar($vars){
    if (emptyempty($vars)) {
      return;
    }
    if (is_array($vars)) {
      $this->vars = $vars;
    }
  }

  /**
   * 設置要請求的URL地址
   * @param string $url 須要設置的URL地址
   * @return void
   */
  public function setUrl($url){
    if ($url != '') {
      $this->uri = $url;
    }
  }

  /**
   * 發送HTTP GET請求
   * @param string $url 若是初始化對象的時候沒有設置或者要設置不一樣的訪問URL,能夠傳本參數
   * @param array $vars 須要單獨返送的GET變量
   * @param array /string 須要設置的頭信息,能夠是一個 相似 array('Host: example.com', 'Accept-Language: zh-cn') 的頭信息數組
   *         或單一的一條相似於 'Host: example.com' 頭信息字符串
   * @param string /array 須要設置的Cookie信息,一個相似於 'name1=value1&name2=value2' 的Cookie字符串信息,
   *         或者是一個 array('name1'=>'value1', 'name2'=>'value2') 的一維數組
   * @param int $timeout 鏈接對方服務器訪問超時時間,單位爲秒
   * @param array $options 當前操做類一些特殊的屬性設置
   * @return unknown
   */
  public function get($url = '' , $vars = array() , $header = array() , $cookie = '' , $timeout = 5 , $options = array()){
    $this->setUrl($url);
    $this->setHeader($header);
    $this->setCookie($cookie);
    $this->setVar($vars);
    return $this->send('GET' , $timeout);
  }

  /**
   * 發送HTTP POST請求
   * @param string $url 若是初始化對象的時候沒有設置或者要設置不一樣的訪問URL,能夠傳本參數
   * @param array $vars 須要單獨返送的GET變量
   * @param array /string 須要設置的頭信息,能夠是一個 相似 array('Host: example.com', 'Accept-Language: zh-cn') 的頭信息數組
   *         或單一的一條相似於 'Host: example.com' 頭信息字符串
   * @param string /array 須要設置的Cookie信息,一個相似於 'name1=value1&name2=value2' 的Cookie字符串信息,
   *         或者是一個 array('name1'=>'value1', 'name2'=>'value2') 的一維數組
   * @param int $timeout 鏈接對方服務器訪問超時時間,單位爲秒
   * @param array $options 當前操做類一些特殊的屬性設置
   * @return unknown
   */
  public function post($url = '' , $vars = array() , $header = array() , $cookie = '' , $timeout = 5 , $options = array()){
    $this->setUrl($url);
    $this->setHeader($header);
    $this->setCookie($cookie);
    $this->setVar($vars);
    return $this->send('POST' , $timeout);
  }

  /**
   * 發送HTTP請求核心函數
   * @param string $method 使用GET仍是POST方式訪問
   * @param array $vars 須要另外附加發送的GET/POST數據
   * @param int $timeout 鏈接對方服務器訪問超時時間,單位爲秒
   * @param array $options 當前操做類一些特殊的屬性設置
   * @return string 返回服務器端讀取的返回數據
   */
  public function send($method = 'GET' , $timeout = 5 , $options = array()){
    //處理參數是否爲空   
    if ($this->uri == '') {
      throw new Exception(__CLASS__ . ": Access url is empty");
    }
    //處理GET請求參數   
    if ($method == 'GET' && !emptyempty($this->vars)) {
      $query = Http::makeQuery($this->vars);
      $parse = parse_url($this->uri);
      $sep = isset($parse['query']) && ($parse['query'] != '') ? '&' : '?';
      $this->uri .= $sep . $query;
    }
    //處理POST請求數據   
    $data = '';
    if ($method == 'POST' && !emptyempty($this->vars)) {
      $data = Http::makeQuery($this->vars);
      $this->setHeader('Content-Type: application/x-www-form-urlencoded');
      $this->setHeader('Content-Length: ' . strlen($data));
    }
    //解析URL地址   
    $url = parse_url($this->uri);
    $host = $url['host'];
    $port = isset($url['port']) && ($url['port'] != '') ? $url['port'] : 80;
    $path = isset($url['path']) && ($url['path'] != '') ? $url['path'] : '/';
    $path .= isset($url['query']) ? "?" . $url['query'] : '';
    //組織HTTP請求頭信息   
    array_unshift(&$this->header , $method . " " . $path . " HTTP/1.1");
    $this->setHeader('User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1)');
    if (!preg_match("/^[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}$/" , $host)) {
      $this->setHeader("Host: " . $host);
    }
    if ($this->cookies != '') {
      $this->setHeader("Cookie: " . $this->cookies);
    }
    $this->setHeader("Connection: Close");
    //'Accept-Language: zh-cn',   
    //'Cache-Control: no-cache',   
    //構造請求信息   
    $header = '';
    foreach ($this->header as $h) {
      $header .= $h . "\r\n";
    }
    $header .= "\r\n";
    if ($method == 'POST' && $data != '') {
      $header .= $data . "\r\n";
    }
    //鏈接服務器發送請求數據   
    $ip = gethostbyname($host);
    if (!($fp = fsockopen($ip , $port , &$errno , &$errstr , $timeout))) {
      throw new Exception(__CLASS__ . ": Can't connect $host:$port, errno:$errno,message:$errstr");
    }
    fputs($fp , $header);
    $lineSize = 1024;
    //處理301,302跳轉頁面訪問   
    $line = fgets($fp , $lineSize);
    $first = preg_split("/\s/" , trim($line));
    if (isset($first[1]) && in_array($first[1] , array('301' , '302'))) {
      while (!feof($fp)) {
        $line = fgets($fp , $lineSize);
        $second = preg_split("/\s/" , trim($line));
        if (ucfirst(trim($second[0])) == 'Location:' && $second[1] != '') {
          $this->header = array();
          return $this->get(trim($second[1]));
        }
      }
    }
    //正常讀取返回數據     
    $buf = '';
    $inheader = 1;
    while (!feof($fp)) {
      if ($inheader && ($line == "\n" || $line == "\r\n")) {
        $inheader = 0;
      }
      $line = fgets($fp , $lineSize);
      if ($inheader == 0) {
        $buf .= $line;
      }
    }
    fclose($fp);
    return $buf;
  }
}

/**
 * 使用文件流操做函數爲核心操做的HTTP訪問接口
 * @desc stream_* 和 fopen/file_get_contents 是PHP內置的一個流和文件操做接口,必須打開 fsockopen 函數本類才能工做,
 *    同時確保其餘相關網絡環境和配置是正確的,包括 allow_url_fopen 等設置
 */
class Http_Stream{
  /**
   * @var object 對象單例
   */
  static $_instance = NULL;
  /**
   * @var string 須要發送的cookie信息
   */
  private $cookies = '';
  /**
   * @var array 須要發送的頭信息
   */
  private $header = array();
  /**
   * @var string 須要訪問的URL地址
   */
  private $uri = '';
  /**
   * @var array 須要發送的數據
   */
  private $vars = array();

  /**
   * 構造函數
   * @param string $configFile 配置文件路徑
   */
  private function __construct($url){
    $this->uri = $url;
  }

  /**
   * 保證對象不被clone
   */
  private function __clone(){
  }

  /**
   * 獲取對象惟一實例
   * @param string $configFile 配置文件路徑
   * @return object 返回本對象實例
   */
  public static function getInstance($url = ''){
    if (!(self::$_instance instanceof self)) {
      self::$_instance = new self($url);
    }
    return self::$_instance;
  }

  /**
   * 設置須要發送的HTTP頭信息
   * @param array /string 須要設置的頭信息,能夠是一個 相似 array('Host: example.com', 'Accept-Language: zh-cn') 的頭信息數組
   *       或單一的一條相似於 'Host: example.com' 頭信息字符串
   * @return void
   */
  public function setHeader($header){
    if (emptyempty($header)) {
      return;
    }
    if (is_array($header)) {
      foreach ($header as $k => $v) {
        $this->header[] = is_numeric($k) ? trim($v) : (trim($k) . ": " . trim($v));
      }
    } elseif (is_string($header)) {
      $this->header[] = $header;
    }
  }

  /**
   * 設置Cookie頭信息
   * 注意:本函數只能調用一次,下次調用會覆蓋上一次的設置
   * @param string /array 須要設置的Cookie信息,一個相似於 'name1=value1&name2=value2' 的Cookie字符串信息,
   *         或者是一個 array('name1'=>'value1', 'name2'=>'value2') 的一維數組
   * @return void
   */
  public function setCookie($cookie){
    if (emptyempty($cookie)) {
      return;
    }
    if (is_array($cookie)) {
      $this->cookies = Http::makeQuery($cookie , ';');
    } elseif (is_string($cookie)) {
      $this->cookies = $cookie;
    }
  }

  /**
   * 設置要發送的數據信息
   * 注意:本函數只能調用一次,下次調用會覆蓋上一次的設置
   * @param array 設置須要發送的數據信息,一個相似於 array('name1'=>'value1', 'name2'=>'value2') 的一維數組
   * @return void
   */
  public function setVar($vars){
    if (emptyempty($vars)) {
      return;
    }
    if (is_array($vars)) {
      $this->vars = $vars;
    }
  }

  /**
   * 設置要請求的URL地址
   * @param string $url 須要設置的URL地址
   * @return void
   */
  public function setUrl($url){
    if ($url != '') {
      $this->uri = $url;
    }
  }

  /**
   * 發送HTTP GET請求
   * @param string $url 若是初始化對象的時候沒有設置或者要設置不一樣的訪問URL,能夠傳本參數
   * @param array $vars 須要單獨返送的GET變量
   * @param array /string 須要設置的頭信息,能夠是一個 相似 array('Host: example.com', 'Accept-Language: zh-cn') 的頭信息數組
   *         或單一的一條相似於 'Host: example.com' 頭信息字符串
   * @param string /array 須要設置的Cookie信息,一個相似於 'name1=value1&name2=value2' 的Cookie字符串信息,
   *         或者是一個 array('name1'=>'value1', 'name2'=>'value2') 的一維數組
   * @param int $timeout 鏈接對方服務器訪問超時時間,單位爲秒
   * @param array $options 當前操做類一些特殊的屬性設置
   * @return unknown
   */
  public function get($url = '' , $vars = array() , $header = array() , $cookie = '' , $timeout = 5 , $options = array()){
    $this->setUrl($url);
    $this->setHeader($header);
    $this->setCookie($cookie);
    $this->setVar($vars);
    return $this->send('GET' , $timeout);
  }

  /**
   * 發送HTTP POST請求
   * @param string $url 若是初始化對象的時候沒有設置或者要設置不一樣的訪問URL,能夠傳本參數
   * @param array $vars 須要單獨返送的GET變量
   * @param array /string 須要設置的頭信息,能夠是一個 相似 array('Host: example.com', 'Accept-Language: zh-cn') 的頭信息數組
   *         或單一的一條相似於 'Host: example.com' 頭信息字符串
   * @param string /array 須要設置的Cookie信息,一個相似於 'name1=value1&name2=value2' 的Cookie字符串信息,
   *         或者是一個 array('name1'=>'value1', 'name2'=>'value2') 的一維數組
   * @param int $timeout 鏈接對方服務器訪問超時時間,單位爲秒
   * @param array $options 當前操做類一些特殊的屬性設置
   * @return unknown
   */
  public function post($url = '' , $vars = array() , $header = array() , $cookie = '' , $timeout = 5 , $options = array()){
    $this->setUrl($url);
    $this->setHeader($header);
    $this->setCookie($cookie);
    $this->setVar($vars);
    return $this->send('POST' , $timeout);
  }

  /**
   * 發送HTTP請求核心函數
   * @param string $method 使用GET仍是POST方式訪問
   * @param array $vars 須要另外附加發送的GET/POST數據
   * @param int $timeout 鏈接對方服務器訪問超時時間,單位爲秒
   * @param array $options 當前操做類一些特殊的屬性設置
   * @return string 返回服務器端讀取的返回數據
   */
  public function send($method = 'GET' , $timeout = 5 , $options = array()){
    //處理參數是否爲空   
    if ($this->uri == '') {
      throw new Exception(__CLASS__ . ": Access url is empty");
    }
    $parse = parse_url($this->uri);
    $host = $parse['host'];
    //處理GET請求參數   
    if ($method == 'GET' && !emptyempty($this->vars)) {
      $query = Http::makeQuery($this->vars);
      $sep = isset($parse['query']) && ($parse['query'] != '') ? '&' : '?';
      $this->uri .= $sep . $query;
    }
    //處理POST請求數據   
    $data = '';
    if ($method == 'POST' && !emptyempty($this->vars)) {
      $data = Http::makeQuery($this->vars);
    }
    //設置缺省頭   
    $this->setHeader('User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1)');
    if (!preg_match("/^[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}$/" , $host)) {
      $this->setHeader("Host: " . $host);
    }
    if ($this->cookies != '') {
      $this->setHeader("Cookie: " . $this->cookies);
    }
    $this->setHeader("Connection: Close");
    //'Accept-Language: zh-cn',   
    //'Cache-Control: no-cache',           
    //構造頭信息   
    $opts = array('http' => array('method' => $method , 'timeout' => $timeout ,));
    if ($data != '') {
      $opts['http']['content'] = $data;
    }
    $opts['http']['header'] = '';
    foreach ($this->header as $h) {
      $opts['http']['header'] .= $h . "\r\n";
    }
    //print_r($opts);exit;   
    //讀取擴展設置選項   
    if (!emptyempty($options)) {
      isset($options['proxy']) ? $opts['http']['proxy'] = $options['proxy'] : '';
      isset($options['max_redirects']) ? $opts['http']['max_redirects'] = $options['max_redirects'] : '';
      isset($options['request_fulluri']) ? $opts['http']['request_fulluri'] = $options['request_fulluri'] : '';
    }
    //發送數據返回   
    $context = stream_context_create($opts);
    if (($buf = file_get_contents($this->uri , null , $context)) === false) {
      throw new Exception(__CLASS__ . ": file_get_contents(" . $this->uri . ") fail");
    }
    return $buf;
  }
}
相關文章
相關標籤/搜索