PHP封装的HttpClient类用法实例

本文实例讲述了PHP封装的HttpClient类。分享给大家供大家参考。具体分析如下:

这是一段php封装的HttpClient类,可实现GET POST Cookie Session等简单的功能。原来做过,这两天重新修改了一下。

<?php
/*
 * Filename: httpclient.php
 * Created on 2012-12-21
 * Created by RobinTang
 * To change the template for this generated file go to
 * Window - Preferences - PHPeclipse - PHP - Code Templates
 */
class SinCookie {
  public $name; // Cookie名称
  public $value; // Cookie值
  // 下面三个属性现在未实现
  public $expires; // 过期时间
  public $path; // 路径
  public $domain; // 域
  // 从Cookie字符串创建一个Cookie对象
  function __construct($s = false) {
    if ($s) {
      $i1 = strpos($s, '=');
      $i2 = strpos($s, ';');
      $this->name = trim(substr($s, 0, $i1));
      $this->value = trim(substr($s, $i1 +1, $i2 - $i1 -1));
    }
  }
  // 获取Cookie键值对
  function getKeyValue() {
    return "$this->name=$this->value";
  }
}
// 会话上下文
class SinHttpContext {
  public $cookies; // 会话Cookies
  public $referer; // 前一个页面地址
  function __construct() {
    $this->cookies = array ();
    $this->refrer = "";
  }
  // 设置Cookie
  function cookie($key, $val) {
    $ck = new SinCookie();
    $ck->name = $key;
    $ck->value = $val;
    $this->addCookie($ck);
  }
  // 添加Cookie
  function addCookie($ck) {
    $this->cookies[$ck->name] = $ck;
  }
  // 获取Cookies字串,请求时用到
  function cookiesString() {
    $res = '';
    foreach ($this->cookies as $ck) {
      $res .= $ck->getKeyValue() . ';';
    }
    return $res;
  }
}
// Http请求对象
class SinHttpRequest {
  public $url; // 请求地址
  public $method = 'GET'; // 请求方法
  public $host; // 主机
  public $path; // 路径
  public $scheme; // 协议,http
  public $port; // 端口
  public $header; // 请求头
  public $body; // 请求正文
  // 设置头
  function setHeader($k, $v) {
    if (!isset ($this->header)) {
      $this->header = array ();
    }
    $this->header[$k] = $v;
  }
  // 获取请求字符串
  // 包含头和请求正文
  // 获取之后直接写socket就行
  function reqString() {
    $matches = parse_url($this->url);
    !isset ($matches['host']) && $matches['host'] = '';
    !isset ($matches['path']) && $matches['path'] = '';
    !isset ($matches['query']) && $matches['query'] = '';
    !isset ($matches['port']) && $matches['port'] = '';
    $host = $matches['host'];
    $path = $matches['path'] ? $matches['path'] . ($matches['query'] ? '?' . $matches['query'] : '') : '/';
    $port = !empty ($matches['port']) ? $matches['port'] : 80;
    $scheme = $matches['scheme'] ? $matches['scheme'] : 'http';
    $this->host = $host;
    $this->path = $path;
    $this->scheme = $scheme;
    $this->port = $port;
    $method = strtoupper($this->method);
    $res = "$method $path HTTP/1.1\r\n";
    $res .= "Host: $host\r\n";
    if ($this->header) {
      reset($this->header);
      while (list ($k, $v) = each($this->header)) {
        if (isset ($v) && strlen($v) > 0)
          $res .= "$k: $v\r\n";
      }
    }
    $res .= "\r\n";
    if ($this->body) {
      $res .= $this->body;
      $res .= "\r\n\r\n";
    }
    return $res;
  }
}
// Http响应
class SinHttpResponse {
  public $scheme; // 协议
  public $stasus; // 状态,成功的时候是ok
  public $code; // 状态码,成功的时候是200
  public $header; // 响应头
  public $body; // 响应正文
  function __construct() {
    $this->header = array ();
    $this->body = null;
  }
  function setHeader($key, $val) {
    $this->header[$key] = $val;
  }
}
// HttpClient
class SinHttpClient {
  public $keepcontext = true; // 是否维持会话
  public $context; // 上下文
  public $request; // 请求
  public $response; // 响应
  public $debug = false;
  // 是否在Debug模式,
  //为true的时候会打印出请求内容和相同的头部
  function __construct() {
    $this->request = new SinHttpRequest();
    $this->response = new SinHttpResponse();
    $this->context = new SinHttpContext();
    $this->timeout = 15; // 默认的超时为15s
  }
  // 清除上一次的请求内容
  function clearRequest() {
    $this->request->body = '';
    $this->request->setHeader('Content-Length', false);
    $this->request->setHeader('Content-Type', false);
  }
  // post方法
  // data为请求的数据
  // 为键值对的时候模拟表单提交
  // 其他时候为数据提交,提交的形式为xml
  // 如有其他需求,请自行扩展
  function post($url, $data = false) {
    $this->clearRequest();
    if ($data) {
      if (is_array($data)) {
        $con = http_build_query($data);
        $this->request->setHeader('Content-Type', 'application/x-www-form-urlencoded');
      } else {
        $con = $data;
        $this->request->setHeader('Content-Type', 'text/xml; charset=utf-8');
      }
      $this->request->body = $con;
      $this->request->method = "POST";
      $this->request->setHeader('Content-Length', strlen($con));
    }
    $this->startRequest($url);
  }
  // get方法
  function get($url) {
    $this->clearRequest();
    $this->request->method = "GET";
    $this->startRequest($url);
  }
  // 该方法为内部调用方法,不用直接调用
  function startRequest($url) {
    $this->request->url = $url;
    if ($this->keepcontext) {
      // 如果保存上下文的话设置相关信息
      $this->request->setHeader('Referer', $this->context->refrer);
      $cks = $this->context->cookiesString();
      if (strlen($cks) > 0)
        $this->request->setHeader('Cookie', $cks);
    }
    // 获取请求内容
    $reqstring = $this->request->reqString();
    if ($this->debug)
      echo "Request:\n$reqstring\n";
    try {
      $fp = fsockopen($this->request->host, $this->request->port, $errno, $errstr, $this->timeout);
    } catch (Exception $ex) {
      echo $ex->getMessage();
      exit (0);
    }
    if ($fp) {
      stream_set_blocking($fp, true);
      stream_set_timeout($fp, $this->timeout);
      // 写数据
      fwrite($fp, $reqstring);
      $status = stream_get_meta_data($fp);
      if (!$status['timed_out']) { //未超时
        // 下面的循环用来读取响应头部
        while (!feof($fp)) {
          $h = fgets($fp);
          if ($this->debug)
            echo $h;
          if ($h && ($h == "\r\n" || $h == "\n"))
            break;
          $pos = strpos($h, ':');
          if ($pos) {
            $k = strtolower(trim(substr($h, 0, $pos)));
            $v = trim(substr($h, $pos +1));
            if ($k == 'set-cookie') {
              // 更新Cookie
              if ($this->keepcontext) {
                $this->context->addCookie(new SinCookie($v));
              }
            } else {
              // 添加到头里面去
              $this->response->setHeader($k, $v);
            }
          } else {
            // 第一行数据
            // 解析响应状态
            $preg = '/^(\S*) (\S*) (.*)$/';
            preg_match_all($preg, $h, $arr);
            isset ($arr[1][0]) & $this->response->scheme = trim($arr[1][0]);
            isset ($arr[2][0]) & $this->response->stasus = trim($arr[2][0]);
            isset ($arr[3][0]) & $this->response->code = trim($arr[3][0]);
          }
        }
        // 获取响应正文长度
        $len = (int) $this->response->header['content-length'];
        $res = '';
        // 下面的循环读取正文
        while (!feof($fp) && $len > 0) {
          $c = fread($fp, $len);
          $res .= $c;
          $len -= strlen($c);
        }
        $this->response->body = $res;
      }
      // 关闭Socket
      fclose($fp);
      // 把返回保存到上下文维持中
      $this->context->refrer = $url;
    }
  }
}
// demo
// now let begin test it
$client = new SinHttpClient(); // create a client
$client->get('http://www.baidu.com/');  // get
echo $client->response->body; // echo
?>

希望本文所述对大家的php程序设计有所帮助。

(0)

相关推荐

  • httpclient模拟post请求json封装表单数据的实现方法

    废话不说上代码: public static String httpPostWithJSON(String url) throws Exception { HttpPost httpPost = new HttpPost(url); CloseableHttpClient client = HttpClients.createDefault(); String respContent = null; // json方式 JSONObject jsonParam = new JSONObject(

  • 完成OSS.Http底层HttpClient重构封装 支持标准库

    OSS.Http项目对于.Net Standard标准库的支持已经迁移完毕,OSS开源系列两个最底层的类库已经具备跨运行时支持的能力.由于OSS.Http类库是几年前我参照RestSharp的思路,完成的一个轻量型Http请求框架.因为时间较久底层使用的还是HttpWebRequest,这次基本上是完全重构,这篇文章主要包含 1. HttpClient的介绍,2. 重构的思路, 3. 容易遇到的问题. 一. httpclient的基本介绍 HttpClient应该是在.net framework

  • Android中HttpURLConnection与HttpClient的使用与封装

    1.写在前面 大部分andriod应用需要与服务器进行数据交互,HTTP.FTP.SMTP或者是直接基于SOCKET编程都可以进行数据交互,但是HTTP必然是使用最广泛的协议.     本文并不针对HTTP协议的具体内容,仅探讨android开发中使用HTTP协议访问网络的两种方式--HttpURLConnection和HttpClient     因为需要访问网络,需在AndroidManifest.xml中添加如下权限 <uses-permission android:name="an

  • PHP封装的HttpClient类用法实例

    本文实例讲述了PHP封装的HttpClient类.分享给大家供大家参考.具体分析如下: 这是一段php封装的HttpClient类,可实现GET POST Cookie Session等简单的功能.原来做过,这两天重新修改了一下. <?php /* * Filename: httpclient.php * Created on 2012-12-21 * Created by RobinTang * To change the template for this generated file go

  • java中封装JDBC工具类的实例分析

    对于能够重复使用的代码,我们最好的方法是对它们进行封装,然后在下次使用的使用就可以直接调用了.本篇所要提到的是JDBC工具类,相信大家在学习java时都接触过.那么对于封装它的方法,本篇先对工具类进行简单的说明,列出有关的封装步骤,然后带来相关的实例. 1.说明 在java开发过程中,代码中时常用到一些Scanner.Random一样的类,他们是键盘录入,生成随机数的类,像一个工具一样,在java中被称为工具类. 2.步骤 封装JDBC工具类 加入获取数据库连接对象的方法 加入释放连接的方法 3

  • php封装的smartyBC类完整实例

    本文实例讲述了php封装的smartyBC类.分享给大家供大家参考,具体如下: <?php /** * Project: Smarty: the PHP compiling template engine * File: SmartyBC.class.php * SVN: $Id: $ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Les

  • Python中Class类用法实例分析

    本文实例讲述了Python中Class类用法.分享给大家供大家参考,具体如下: 尽管Python在Function Programming中有着其他语言难以企及的的优势,但是我们也不要忘了Python也是一门OO语言哦.因此我们关注Python在FP上的优势的同时,还得了解一下Python在OO方面的特性. 要讨论Python的OO特性,了解Python中的Class自然是首当其冲了.在Python中定义class和创建对象实例都很简单,具体代码如下: class GrandPa: def __

  • php封装的smarty类完整实例

    本文实例讲述了php封装的smarty类.分享给大家供大家参考,具体如下: <?php /** * Project: Smarty: the PHP compiling template engine * File: Smarty.class.php * SVN: $Id: Smarty.class.php 4848 2014-06-08 18:12:09Z Uwe.Tews@googlemail.com $ * This library is free software; you can re

  • php封装的mysqli类完整实例

    本文实例讲述了php封装的mysqli类.分享给大家供大家参考,具体如下: 类: <?php header('content-type:text/html;charset=utf-8'); /* 掌握满足单例模式的必要条件 (1)私有的构造方法-为了防止在类外使用new关键字实例化对象 (2)私有的成员属性-为了防止在类外引入这个存放对象的属性 (3)私有的克隆方法-为了防止在类外通过clone成生另一个对象 (4)公有的静态方法-为了让用户进行实例化对象的操作 */ class Connect

  • php文件压缩之PHPZip类用法实例

    本文实例讲述了php文件压缩之PHPZip类用法.分享给大家供大家参考.具体如下: <?php // // PHPZip v1.2 by Sext (sext@neud.net) // // Makes zip archive // // Based on "Zip file creation class", uses zLib // // class PHPZip { function Zip($dir, $zipfilename) { if (@function_exists

  • php的ZipArchive类用法实例

    本文实例讲述了php的ZipArchive类用法,分享给大家供大家参考.具体如下: 通常来说,php5.2开始支持ZipArchive类,php4只能使用zip函数.其实在官方实现zip类之前,已经有大牛贡献了打包解压zip文件的方法.现在php包含了ZipArchive类,当然优先使用.使用该类能创建和解压zip文件,也能直接读取zip压缩包内的内容,很方便,这里主要总结下读取和解压的过程. 解压一个包到指定目录: 复制代码 代码如下: <?php $zip = new ZipArchive;

  • java中Calendar类用法实例详解

    本文实例讲述了java中Calendar类用法.分享给大家供大家参考,具体如下: java中的Calendar在开发中经常被忽略,这篇博客总结一下这个类,对后面项目中使用时期的时候有帮助. Calendar常量(field)的作用 Calendar cal = Calendar.getInstance(); cal.get(Calendar.DATE);//-----------------------当天 1-31 cal.get(Calendar.DAY_OF_MONTH);//------

  • ES6中class类用法实例浅析

    本文实例讲述了ES6中class类用法.分享给大家供大家参考,具体如下: 类语法是ES6中新增的一个亮点特色.我们熟悉的JavaScript终于迎来了真正意义上的类.在之前,想要通过javascript来实现类,通常会采用如下构造函数的模式: function Person(name,age,job){ this.name = name; this.age = age; this.job = job; this.friends = ['Shelby','Court']; } Person.pro

随机推荐