原标题:PHP HTTP客户端-Guzzle原理解析

本文适合寻找PHP HTTP客户端库,或者对于Guzzle的使用和实现原理比较感兴趣的同学阅读,需要具备一定的PHP基础知识。

一、背景

在PHP后台开发过程中,经常会遇到模块间需要通过HTTP通信的情形。PHP语言本身只提供了socket操作的接口,并未提供HTTP相关操作的接口。许多现有的实现采用curl扩展充当HTTP Client与HTTP Server通信,但仍需自己封装curl的接口。有鉴于此,本文介绍一款流行的PHP HTTP Client客户端---Guzzle(https://github.com/guzzle/guzzle/)的用法,深入分析其底层实现原理。

二、Guzzle用法

例如使用Guzzle访问http://www.baidu.com的代码:

<?php $client = new GuzzleHttpClient();$response = $client->request('GET', 'http://www.baidu.com', [ "timeout" => 3000]);echo $response->getStatusCode(), "n";echo $response->getBody();

接口封装是不是十分简单?只需要关心请求方法,目标url和请求的选项即可快速上手。同时,Guzzle还支持异步请求方式:

<?phpuse GuzzleHttpExceptionRequestException;use PsrHttpMessageResponseInterface;$client = new GuzzleHttpClient();$promise = $client->requestAsync('GET', 'http://www.baidu.com');$promise->then( function (ResponseInterface $res) { echo $res->getStatusCode() . "n"; echo $res->getBody(); return $res; }, function (RequestException $e) { echo $e->getMessage() . "n"; echo $e->getRequest()->getMethod(); })->wait();

基于异步请求,Guzzle还实现了并发请求,关于Guzzle的具体使用方法可以参考其中文文档http://guzzle-cn.readthedocs.io/zh_CN/latest/index.html。

三、Guzzle实现原理 1.client构造

GuzzleHttpClient类构造函数声明为:

public function __construct(array $config = [])

$config配置使得用户可以根据需要配置一切可以配置的选项,包括allowredirects、auth、connecttimeout、proxy等。除此之外,还可以自定义请求的处理函数handler,方便应用程序扩展,handler接口规范为:

function handler($request, array $options);

处理成功时,接口返回PsrHttpMessageResponseInterface;失败时返回GuzzleHttpExceptionRequestException异常。

默认情形下,GuzzleHttpHandlerStack::create会创建请求处理函数

public static function create(callable $handler = null){ $stack = new self($handler ?: choose_handler()); $stack->push(Middleware::httpErrors(), 'http_errors'); $stack->push(Middleware::redirect(), 'allow_redirects'); $stack->push(Middleware::cookies(), 'cookies'); $stack->push(Middleware::prepareBody(), 'prepare_body'); return $stack;}

create函数以堆栈的形式创建了一系列的处理函数,包括http异常、重定向、cookie和prepare_body。处理函数返回的函数闭包为:

return function (callable $handler) { return function ($request, array $options) use ($handler) { ... };};

函数入参为handler,返回一个新的handler,这样可以将所有的处理函数链接在一起,最终生成一个符合handler接口规范的函数.

choose_handler函数选择stack中的起始handler,选择策略为:

扩展自带curl_multi_exec和curl_exec函数则根据$options中的synchronous选项决定,empty(synchronous)为false则使用CurlHandler,否则使用CurlMultiHandler

扩展只有curl_exec函数则使用CurlHandler

扩展只有curl_multi_exec函数则使用CurlMultiHandler

最后,如果php.ini中开启了allow_url_fopen,则根据$options中的stream选项决定,empty(stream)为false则使用StreamHandler。

2.client调用request方法

request方法实现为:

public function request($method, $uri = '', array $options = []){ $options[RequestOptions::SYNCHRONOUS] = true; return $this->requestAsync($method, $uri, $options)->wait();}

由此可见,request事实上是采用了requestAsync异步方法+wait来完成的,也就是异步转同步。

2.1 requestAsync

requestAsync将请求信息包装成Psr7Request对象,然后调用

transfer(RequestInterface $request, array $options)

transfer函数最终返回Promisepromise_for($handler($request, $options)); 其中$handler即为构造函数中所设置的stack,stack中存放一系列的请求处理函数。 HandlerStack的处理函数为:

public function __invoke(RequestInterface $request, array $options){ $handler = $this->resolve(); return $handler($request, $options);}

resolve方法解析整个stack,返回一个包装后的handler,包装策略为按照出栈顺序包装,也就是

foreach (array_reverse($this->stack) as $fn) { $prev = $fn[0]($prev);}

典型的中间件模型,所有的处理函数串接在一起了。请求经由http_errors、allow_redirects等处理之后到达Curl,执行真正的网络交互。

对于同步的handler如CurlHandler,在此处会执行curl_exec发起请求,最终返回的是FulfilledPromise对象或RejectedPromise对象,代表请求已经处理完毕。

对于异步的handler比如CurlMultiHandler,在此处并不会执行curl_multi_exec,而是返回一个promise对象,里面注册了需要等待执行的curl_multi_exec。

Curl Handler处理完成之后,往上回溯,在Allow_redirects和Http_errors部分会进入then方法,最终返回的结果都是promise对象。

2.2 wait

请求发送完毕,进入promise的wait操作,最终会执行promise的$waitFn函数。

对于CurlMultiHandler,$waitFn即执行curl_multi_exec进行网络交互,然后调用resolve方法将response对象传递到then方法的$onFulfilled函数。

对于CurlHandler,直接利用resolve将response对象传递到$onFulfilled函数。

这样,异步的then方法设置的回调就可以接收到response了。 then方法最终返回response,这个对象又可以作为返回值返回,这样同步的wait就可以通过返回值来获取response对象了。

四、总结

本文重点介绍了Guzzle同步和异步请求的实现原理,除此之外,Guzzle还提供了并行请求,请求pool等实现,读者可以在此基础上继续深入。

本文来源网络,侵立删!返回搜狐,查看更多

责任编辑:

php guzzlehttp,PHP HTTP客户端-Guzzle原理解析相关推荐

  1. gRPC客户端创建和调用原理解析

    1. gRPC客户端创建流程 1.1. 背景 gRPC是在HTTP/2之上实现的RPC框架,HTTP/2是第7层(应用层)协议,它运行在TCP(第4层 - 传输层)协议之上,相比于传统的REST/JS ...

  2. hbase原理与实践_JAVA连接HBase客户端及HBase写入数据和读取数据原理解析

    JAVA连接HBase客户端 接着上篇文章进行代码的实践,从JAVA 客户端对 HBase的客户端进行一系列操作 工具类:HbaseUtil 静态代码块一次性创建连接对象 并赋值 返回连接对象 Con ...

  3. Ajax跨域:Jsonp原理解析

    推荐先看下这篇文章:JS跨域(ajax跨域.iframe跨域)解决方法及原理详解(jsonp) JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重 ...

  4. Tomcat 架构原理解析到架构设计借鉴

    ‍ 点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 Tomcat 架构原理解析到架构设计借鉴 Tomcat 发展这 ...

  5. JSONP跨域的原理解析

    JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重要的安全性限制,被称为"Same-Origin Policy"(同源策略). ...

  6. RocketMQ原理解析-producer 4.发送分布式事物消息

    2019独角兽企业重金招聘Python工程师标准>>> RocketMQ原理解析-producer 4.发送分布式事物消息 博客分类: MQ 为什么消息要具备事务能力 还是比较清晰的 ...

  7. Java开发中Netty线程模型原理解析!

    Java开发中Netty线程模型原理解析,Netty是Java领域有名的开源网络库具有高性能和高扩展性的特点,很多流行的框架都是基于它来构建.Netty 线程模型不是一成不变的,取决于用户的启动参数配 ...

  8. 6、HIVE JDBC开发、UDF、体系结构、Thrift服务器、Driver、元数据库Metastore、数据库连接模式、单/多用户模式、远程服务模式、Hive技术原理解析、优化等(整理的笔记)

    目录: 5 HIVE开发 5.1 Hive JDBC开发 5.2 Hive UDF 6 Hive的体系结构 6.2 Thrift服务器 6.3 Driver 6.4 元数据库Metastore 6.5 ...

  9. AOP—JVM SandBox—底层原理解析

    原文作者:陆晨 原文地址:JVM SandBox 的技术原理与应用分析 目录 一.前言 二.JVM SandBox 简介 2.1 AOP 2.2 JVM SandBox 三.JVM 核心技术 3.1 ...

  10. clickhouse原理解析与应用实践_Hybrid App (混合应用) 技术全解析 方案原理篇

    引言 随着 Web 技术和移动设备的快速发展,Hybrid 技术已经成为一种最主流最常见的方案.一套好的 Hybrid架构方案 能让 App 既能拥有极致的体验和性能,同时也能拥有 Web技术 灵活的 ...

最新文章

  1. 杜克大学和Facebook联手开发更好的光通信
  2. selenium2与python自动化6-select下拉框
  3. 链表之打印两个有序链表的公共部分
  4. 5.一文搞懂MySQL的数据类型
  5. 大学生必须要知道的毕业设计基本流程
  6. vue 列表 萌层 鼠标移入移出_vue鼠标移入添加class样式,鼠标移出去除样式(active)实现方法...
  7. 在WSL下安装MYSQL的实验报告_Linux(wsl)安装docker和mysql主从搭建
  8. java day50【综合案例day02】
  9. Android作业四
  10. MC9S中断函数编写
  11. 使用WDF开发驱动程序
  12. QT With OpenGL(泛光)(Bloom)
  13. 阿里巴巴(Alibaba)笔试编程题
  14. win10下的VMware还原网络设置,无法创建VMware网络适配器解决办法
  15. Android拨打电话权限总结
  16. 二战字节跳动成功上岸,准备了小半年,拿27k也算不上很高吧~
  17. Xilinx的智能门控时钟技术你了解吗?
  18. eclipse maven 搭建 SSM(Spring+SpringMVC+MyBatis)开发环境 和 MyBatis 自动生成的 maven 插件配置
  19. 浏览器书签同步插件EverSync
  20. Quectel BC25 系列 尺寸紧凑、功耗超低 NB-IoT 无线通信模块[移远通信]

热门文章

  1. BDC模式与OKCODE、 CALL TRANSACTION用法
  2. 3月16日----3月20日二年级课程表
  3. ASP.NET 5 Target framework dnx451 and dnxcore50
  4. 支付宝APP支付接口-PHP
  5. 微信公众号数据分析报告
  6. Java第五章 常用API
  7. mysql 月初 月末_月初月末sql语句(日期所在月的第一天,最后一天)
  8. android 指纹比对方法,指纹识别功能方面对比_手机Android频道-中关村在线
  9. 东鹏饮料如何站稳千亿市值?
  10. Linux进程间通信——管道通信详解