HTTP客户端

编辑该页面

HTTP客户端

安装

HttpClient组件是一个低级的HTTP客户端支持PHP流包装器和旋度。它提供了公用事业消费api,支持同步和异步操作。你可以安装它:

1
美元作曲家需要symfony / ht欧宝娱乐app下载地址tp客户端

基本用法

使用HttpClient类请求。在Symfon欧宝娱乐app下载地址y框架中,这个类是可用的http_client服务。此服务将autowired的时自动类型提示为HttpClientInterface:

  • 框架的使用
  • 独立使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30
使用欧宝娱乐app下载地址\合同\HttpClient\HttpClientInterface;欧宝娱乐app下载地址SymfonyDocs{私人美元客户端;公共函数__construct(HttpClientInterface美元客户端){美元- >客户=美元客户端;}公共函数fetchGitHubInformation():数组{美元响应=美元- >客户端- >请求(“得到”,“https://api.github.com/repos/欧宝娱乐app下载地址symfony/symfony-docs”);美元statusCode=美元响应- >getStatusCode ();/ / statusCode = 200美元美元contentType=美元响应- >getHeaders () (“内容类型”][0];/ / $ contentType =“application / json”美元内容=美元响应- >getContent ();/ / $内容= " {" id ": 521583年,“名字”:“sym欧宝娱乐app下载地址fony-docs…}”美元内容=美元响应- >toArray ();/ / $内容= [id = > 521583,“名字”= >“symfony-do欧宝娱乐app下载地址cs”,…]返回美元内容;}}

提示

HTTP客户端与许多常见HTTP客户端可互操作的抽象在PHP。您还可以使用这些抽象从自动装配中获利。看到互操作性为更多的信息。

配置

HTTP客户端包含许多选项,您可能需要充分执行请求的控制方式,包括DNS pre-resolution, SSL参数,公钥将等等。他们可以在全球范围内配置定义(应用于所有请求),每个请求(覆盖任何全局配置)。

您可以配置全球使用的选项default_options选择:

  • YAML
  • XML
  • PHP
  • 独立使用
1 2 3 4 5
#配置/包/ framework.yaml框架:http_client:default_options:max_redirects:7

您还可以使用withOptions ()方法检索客户的一个新实例和新的默认选项:

1 2 3 4
美元- >客户=美元客户端- >withOptions ([“base_uri”= >“https://..”。,“头”= > [“头名称”= >头的值的]]);

本指南中描述了一些选项:

查看完整的http_client配置参考了解所有的选项。

HTTP客户端也有一个配置选项max_host_connections,这个选项不能被一个请求:

  • YAML
  • XML
  • PHP
  • 独立使用
1 2 3 4 5
#配置/包/ framework.yaml框架:http_client:max_host_connections:10#……

范围的客户

常见的一些HTTP客户机选项取决于请求的URL(如发出请求时必须设置一些标题GitHub API而不是其他主机)。如果这是你的情况下,组件提供范围客户(使用ScopingHttpClient)可以使用autoconfigure HTTP客户端根据请求的URL:

  • YAML
  • XML
  • PHP
  • 独立使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
#配置/包/ framework.yaml框架:http_client:scoped_clients:#只有请求匹配范围将使用这些选项github.client:范围:“https://api \ .github \ com”标题:接受:“application / json vnd.github.v3 +”授权:“令牌% env (GITHUB_API_TOKEN) %”#……#使用base_uri,相对url(例如请求(“得到”,“回购/ symfony / symfony-docs”))欧宝娱乐app下载地址#将默认这些选项github.client:base_uri:“https://api.github.com”标题:接受:“application / json vnd.github.v3 +”授权:“令牌% env (GITHUB_API_TOKEN) %”#……

您可以定义几个范围,所以,每个组选项添加只有一个请求的URL匹配的正则表达式之一范围选择。

如果你使用作用域的客户在Symfony框架中,您必须使用Symfo欧宝娱乐app下载地址ny的定义的任何方法选择一个特定的服务。每个客户都有一个独特的服务命名它的配置。

每个范围的客户还定义了相应的自动装配别名命名。如果你使用欧宝娱乐app下载地址Symfony \ \ HttpClient \ HttpClientInterface githubClient美元的合同作为一个参数的类型和名称,自动装配将注入github.client服务到您autowired的类。

请注意

读了base_uri选择文档学习规则应用当合并相对URI的基本URI范围的客户。

发出请求

HTTP客户端提供了一个单身请求()方法来执行各种各样的HTTP请求:

1 2 3 4 5 6 7 8 9 10 11
美元响应=美元客户端- >请求(“得到”,“https://..”。);美元响应=美元客户端- >请求(“职位”,“https://..”。);美元响应=美元客户端- >请求(“把”,“https://..”。);/ /……/ /您可以添加请求选项(或覆盖全球的)使用第三论点美元响应=美元客户端- >请求(“得到”,“https://..”。,(“头”= > [“接受”= >“application / json”、]]);

反应始终是异步的,所以调用方法立即返回而不是等待接收响应:

1 2 3 4 5 6 7 8 9
/ /代码执行立即继续;它不会等待接收响应美元响应=美元客户端- >请求(“得到”,“http://releases.ubuntu.com/18.04.2/ubuntu-18.04.2-desktop-amd64.iso”);/ /获取响应头等待,直到他们到达美元contentType=美元响应- >getHeaders () (“内容类型”][0];/ /想要将块执行,直到响应内容/ /接收到完整的响应内容美元内容=美元响应- >getContent ();

该组件还支持流媒体的反应完全异步应用程序。

身份验证

HTTP客户端支持不同的身份验证机制。他们可以在全球范围内配置定义(可应用于所有请求)和每个请求(覆盖任何全球认证):

  • YAML
  • XML
  • PHP
  • 独立使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#配置/包/ framework.yaml框架:http_client:scoped_clients:example_api:base_uri:“https://example.com/”# HTTP基本身份验证auth_basic:用户名:密码的# HTTP持票人身份验证(也称为令牌认证)auth_bearer:the-bearer-token#微软NTLM身份验证auth_ntlm:用户名:密码的
1 2 3 4 5 6
美元响应=美元客户端- >请求(“得到”,“https://..”。,(/ /只使用不同的HTTP基本身份验证请求“auth_basic”= > [“用户名”,“密码”),/ /……]);

请注意

需要使用cURL传输NTLM身份验证机制。通过使用HttpClient: createForBaseUri (),我们确保授权认证不会被发送到其他主机https://example.com/

查询字符串参数

你可以手动添加到请求的URL,或者定义通过关联数组查询与URL选项,将合并:

1 2 3 4 5 6 7 8
/ /一个HTTP GET请求到https://httpbin.org/get?token=...&name=..。美元响应=美元客户端- >请求(“得到”,“https://httpbin.org/get”,(/ /这些值自动编码之前将它们包含在URL中“查询”= > [“令牌”= >“……”,“名字”= >“……”、]]);

使用选项来定义默认的标题添加到所有请求:

  • YAML
  • XML
  • PHP
  • 独立使用
1 2 3 4 5 6
#配置/包/ framework.yaml框架:http_client:default_options:标题:“用户代理”:“我的应用”

你也可以设置新的标题或覆盖默认的具体要求:

1 2 3 4 5 6 7
/ /这头只包含在请求和覆盖值/ /定义的相同的头如果全球的HTTP客户端美元响应=美元客户端- >请求(“职位”,“https://..”。,(“头”= > [“内容类型”= >“文本/普通”、]]);

上传数据

此组件提供了上传数据使用几种方法身体选择。您可以使用常规字符串,闭包,iterable和资源,他们会被处理时自动使请求:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
美元响应=美元客户端- >请求(“职位”,“https://..”。,(/ /定义数据使用常规字符串“身体”= >“原始数据”,/ /定义数据使用一个参数数组“身体”= > [“parameter1”= >“value1”,“……”),/ /使用闭包生成上传数据“身体”= >函数(int美元大小):字符串{/ /……},/ /使用资源获取数据“身体”= > fopen (“/道路/ /文件”,“r”)));

当上传数据帖子方法,如果你不定义内容类型HTTP头信息明确,Symfony假设你上传表单欧宝娱乐app下载地址数据并添加所需的“内容类型:应用程序/ x-www-form-urlencoded”头给你。

身体选项设置为一个闭包,它会被称为几次,直到它返回空字符串,这标志着身体的终结。每一次,关闭应该返回一个字符串小于请求量作为参数。

一台发电机或任何可否认的还可以使用,而不是一个闭包。

提示

上传JSON载荷时,使用json选择而不是身体。给定的内容将自动json编码的请求将增加内容类型:application / json自动:

1 2 3 4 5
美元响应=美元客户端- >请求(“职位”,“https://..”。,(json的= > [“param1”= >“value1”,“……”)));美元decodedPayload=美元响应- >toArray ();

与文件上传提交表单,是你的责任根据编码的身体多部分/格式内容类型。的欧宝娱乐app下载地址Symfony Mime组件使它几行代码:

1 2 3 4 5 6 7 8 9 10 11 12
使用欧宝娱乐app下载地址\组件\Mime\部分\DataPart;使用欧宝娱乐app下载地址\组件\Mime\部分\多部分\FormDataPart;美元formFields= (“regular_field”= >“有价值”,“file_field”= > DataPart::fromPath (/道路/ /上传文件的),);美元formData=FormDataPart (美元formFields);美元客户端- >请求(“职位”,“https://..”。,(“头”= >美元formData- >getPreparedHeaders ()- >toArray (),“身体”= >美元formData- >bodyToIterable ()));

提示

当使用多维数组FormDataPart类自动添加(例子)字段的名称:

1 2 3 4 5 6 7 8 9
美元formData=FormDataPart ([“array_field”= > [“有价值”,“其他值”、]]);美元formData- >getParts ();/ /返回TextPart的两个实例/ /名称”array_field[0]”和“array_field [1]”

这种行为可以绕过数组使用以下结构:

1 2 3 4 5 6 7
美元formData=FormDataPart ([[“array_field”= >“有价值”]、[“array_field”= >“其他值”)));美元formData- >getParts ();/ /返回TextPart两的两个实例/ /名称“array_field”

默认情况下,HttpClient流身体当上传内容。这可能并不是处理所有服务器,导致HTTP状态码411(“长度”),因为没有内容长度头。解决方案是将身体转化为一个字符串用以下方法(增加内存消耗,当流大):

1 2 3 4
美元客户端- >请求(“职位”,“https://..”。,(/ /……“身体”= >美元formData- >bodyToString ()));

如果您需要添加一个自定义HTTP头信息上传,你能做什么:

1 2
美元=美元formData- >getPreparedHeaders ()- >toArray ();美元[]=“X-Foo:酒吧”;

饼干

该组件提供的HTTP客户端处理cookie是无状态的,但需要有状态存储(因为响应可以更新饼干和他们必须用于后续的请求)。这就是为什么这个组件不会自动处理cookie。

你可以处理饼干自己使用饼干HTTP报头或使用BrowserKit组件它提供了这一特性和与HttpClient无缝集成组件。

重定向

默认情况下,HTTP客户机重定向,最多20,当发出请求。使用max_redirects设置配置这种行为(如果重定向的数量大于配置的价值,你会得到一个RedirectionException):

1 2 3 4
美元响应=美元客户端- >请求(“得到”,“https://..”。,(/ / 0意味着不遵循任何重定向“max_redirects”= >0]);

重试失败的请求

有时,请求失败,因为网络问题或临时的服务器错误。欧宝娱乐app下载地址Symfony的HttpClient允许使用自动重试失败的请求retry_failed选项

默认情况下,请求重试3次失败,和一个指数之间的延迟重试(第一次重试= 1秒;第三个重试:4秒),只有以下HTTP状态代码:423年,425年,429年,502年503年当使用任何HTTP方法和500年,504年,507年510年当使用一个HTTP幂等方法

查看可配置的完整列表retry_failed选项学会如何调整他们每个人来适应您的应用程序需求。

当使用HttpClient类以外的Symfony应用程序中,使用欧宝娱乐app下载地址RetryableHttpClient类来包装你的原始HTTP客户端:

1 2 3
使用欧宝娱乐app下载地址\组件\HttpClient\RetryableHttpClient;美元客户端=RetryableHttpClient (HttpClient::create ());

RetryableHttpClient使用一个RetryStrategyInterface决定是否应该重试请求,定义每个重试之间的等待时间。

HTTP代理

默认情况下,这个组件荣誉的标准操作系统定义环境变量直接通过当地代理HTTP流量。这意味着通常是没有配置客户端与代理合作,提供这些env var是正确配置。

你仍然可以设置或使用覆盖这些设置代理no_proxy选项:

  • 代理应该设置为http://..。通过URL的代理
  • no_proxy为一个以逗号分隔的禁用代理主机不需要它来获得。

进步的回调

通过提供一个可调用的on_progress选择,一个可以跟踪上传/下载完成。这个回调是保证呼吁DNS解析,头和上完成;此外它被称为当新的数据上传或下载并至少每秒一次:

1 2 3 4 5 6 7
美元响应=美元客户端- >请求(“得到”,“https://..”。,(“on_progress”= >函数(int美元dlNow,int美元dlSize数组,美元信息):无效{/ / $ dlNow下载的字节数/ /美元dlSize是下载的总大小或1如果是未知的/ /信息是反应- >美元getInfo()将返回在这个时间}));

从回调将包裹在抛出的任何异常的一个实例TransportExceptionInterface并将中止请求。

HTTPS证书

HttpClient使用系统的证书存储验证SSL证书(在浏览器使用他们自己的商店)。在开发过程中使用自签名证书时,建议创建自己的证书颁发机构(CA)并将它添加到您的系统的商店。

或者,你也可以禁用verify_hostverify_peer(见http_client配置参考),但这是不推荐在生产。

SSRF(服务器端请求伪造)处理

SSRF允许攻击者诱导后端应用程序发出的HTTP请求到任意域。这些攻击目标的内部主机和IPs也可以攻击服务器。

如果你使用一个HttpClient与用户提供的uri,这可能是一个好主意来装饰它NoPrivateNetworkHttpClient。这将确保本地网络不能访问HTTP客户端:

1 2 3 4 5 6 7 8 9 10 11 12 13 14
使用欧宝娱乐app下载地址\组件\HttpClient\HttpClient;使用欧宝娱乐app下载地址\组件\HttpClient\NoPrivateNetworkHttpClient;美元客户端=NoPrivateNetworkHttpClient (HttpClient::create ());/ /请求公共网络时没有什么变化美元客户端- >请求(“得到”,“https://example.com/”);/ /然而,所有请求私人网络现在被违约美元客户端- >请求(“得到”,“http://localhost/”);/ /第二个可选参数定义了网络阻塞/ /在这个例子中,请求从104.26.14.0 104.26.15.255将导致异常/ /但是所有其他请求,包括其他内部网络,将被允许美元客户端=NoPrivateNetworkHttpClient (HttpClient::create (), (“104.26.14.0/23”]);

分析

当你使用TraceableHttpClient回复内容将保存在内存中,排气。

你可以通过设置禁用这个行为extra.trace_content选项在你的请求:

1 2 3
美元响应=美元客户端- >请求(“得到”,“https://..”。,(“额外的”= > [“trace_content”= >)));

这个设置不会影响其他客户。

性能

最大的组件构建HTTP的性能。通过设计,它是兼容与HTTP / 2和做并发异步流和多路复用请求/响应。即使做定期同步调用,这个设计允许请求之间保持连接到远程主机开放,提高性能,节省重复DNS解析,SSL协商,等。利用这些设计好处,cURL扩展是必要的。

启用cURL支持

该组件支持原生PHP流和旋度的HTTP请求。虽然都是可以互换的,提供相同的功能,包括并发请求,HTTP / 2时仅支持使用cURL。

HttpClient: create ()选择旋度运输旋度PHP扩展启用了PHP,落回到流。如果你喜欢显式地选择运输,使用下面的类来创建客户端:

1 2 3 4 5 6 7 8
使用欧宝娱乐app下载地址\组件\HttpClient\CurlHttpClient;使用欧宝娱乐app下载地址\组件\HttpClient\NativeHttpClient;/ /使用原生PHP流美元客户端=NativeHttpClient ();/ /使用cURL PHP扩展美元客户端=CurlHttpClient ();

当使用该组件在一个完整的Symfony应用程序中,这种行为是不可配置的,将使用自动安欧宝娱乐app下载地址装并启用cURL PHP扩展。否则,将使用原生PHP流。

配置CurlHttpClient选项

PHP允许配置很多旋度的选择通过curl_setopt函数。为了使组件更便携当不使用cURLCurlHttpClient只使用其中的一些选项(他们忽视了其他地区的客户)。

添加一个extra.curl选择您的配置通过这些额外的选项:

1 2 3 4 5 6 7 8 9 10 11 12
使用欧宝娱乐app下载地址\组件\HttpClient\CurlHttpClient;美元客户端=CurlHttpClient ();美元客户端- >请求(“职位”,“https://..”。,(/ /……“额外的”= > [“卷”= > [CURLOPT_IPRESOLVE = > CURL_IPRESOLVE_V6]]]);

请注意

一些卷发选项无法覆盖(例如,因为线程安全),你会得到一个异常当试图推翻他们。

HTTP压缩

HTTP报头接受编码:gzip添加自动如果:

  • 当使用cURL客户:旋度与ZLib支持(参见编译php - ri旋度)
  • 当使用本地HTTP客户端:Zlib PHP扩展安装

如果服务器并应对gzip响应,透明地解码。禁用HTTP压缩,发送一个接受编码:身份HTTP报头。

分块传输编码自动启用PHP运行时和远程服务器是否支持它。

HTTP / 2的支持

当请求一个httpsURL,默认启用了HTTP / 2如果安装以下工具:

迫使HTTP / 2httpurl,您需要启用它显式地通过http_version选择:

  • YAML
  • XML
  • PHP
  • 独立使用
1 2 3 4 5
#配置/包/ framework.yaml框架:http_client:default_options:http_version:“2.0”

支持HTTP / 2把作品的使用libcurl > = 7.61时使用PHP > = 7.2.17 / 7.3.4:推动反应时放入临时缓存和使用相应的触发后续请求的url。

处理响应

所有HTTP客户端返回的响应是一个类型的对象ResponseInterface它提供了以下方法:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31
美元响应=美元客户端- >请求(“得到”,“https://..”。);/ /得到响应的HTTP状态代码美元statusCode=美元响应- >getStatusCode ();/ /获取HTTP头作为string[][]的标题名称小写美元=美元响应- >getHeaders ();/ /获取响应主体为字符串美元内容=美元响应- >getContent ();/ /响应JSON内容一个PHP数组美元内容=美元响应- >toArray ();/ /强制类型转换一个PHP流资源的响应内容美元内容=美元响应- >toStream ();/ /取消请求/响应美元响应- >取消();/ /返回信息来自传输层,如“response_headers”,/ /“redirect_count”、“start_time”、“redirect_url”,等等。美元httpInfo=美元响应- >getInfo ();/ /你可以得到个人信息美元开始时间=美元响应- >getInfo (“start_time”);/ /如这个URL返回最后一个响应(如果需要解决重定向)美元url=美元响应- >getInfo (“url”);/ /返回HTTP请求和响应的详细日志事务美元httpLogs=美元响应- >getInfo (“调试”);

请注意

$响应- > getInfo ()非阻塞:它返回生活响应信息。他们中的一些人可能还不知道。http_code当你将它命名。

流媒体的反应

调用流()方法的HTTP客户端响应的顺序而不是等待整个反应:

1 2 3 4 5 6 7 8 9 10 11 12 13 14
美元url=“https://releases.ubuntu.com/18.04.1/ubuntu-18.04.1-desktop-amd64.iso”;美元响应=美元客户端- >请求(“得到”,美元url);/ /响应懒惰:执行这段代码一旦收到标题如果(200年= = !美元响应- >getStatusCode ()) {\异常(“……”);}/ /得到的响应内容块和保存在一个文件中/ /响应块实现Symfony \ \ HttpClien欧宝娱乐app下载地址t \ ChunkInterface合同美元文件句柄= fopen (' / ubuntu.iso ',' w ');foreach(美元客户端- >流(美元响应)作为美元){写入文件(美元文件句柄,美元- >getContent ());}

请注意

默认情况下,文本/ *、JSON和XML响应机构在当地一个缓冲php: / / temp流。你可以控制这种行为通过使用缓冲选择:设置真正的/启用/禁用缓冲,或一个闭包,返回相同的基于接收到的响应头作为参数。

取消回复

中止一个请求(例如,因为它没有完成在适当的时间,或者你只想获取第一个字节的响应,等等),你可以使用取消()的方法ResponseInterface:

1
美元响应- >取消();

从一个进度回调或者抛出一个异常:

1 2 3 4 5 6 7
美元响应=美元客户端- >请求(“得到”,“https://..”。,(“on_progress”= >函数(int美元dlNow,int美元dlSize数组,美元信息):无效{/ /……\ MyException ();}));

除了将裹着的一个实例TransportExceptionInterface并将中止请求。

如果响应是取消使用$响应- >取消(),$响应- > getInfo(取消)将返回真正的

处理异常

有三种类型的异常,这些都实现ExceptionInterface:

当响应的HTTP状态码300 - 599范围(即3 xx, 4 xx或5 xx),getHeaders (),getContent ()toArray ()方法抛出一个适当的异常,所有这些都实现了HttpExceptionInterface

从这个异常退出,并处理300 - 599状态码,通过作为可选参数每一个调用的方法,例如:$响应- > getHeaders(假);

如果你不调用任何这三个方法,仍将抛出的异常时美元的反应对象已经被破坏。

调用$响应- > getStatusCode ()足以禁用此行为(但不要错过自己检查状态代码)。

虽然回答很懒,它们的析构函数总是等待头回来了。这意味着下面的请求完成;如果如404返回,将抛出一个异常:

1 2 3 4
/ /因为返回值不是分配给一个变量,析构函数/ /返回的响应将被立即将抛出如果/ /状态代码是在300 - 599的范围内美元客户端- >请求(“职位”,“https://..”。);

这反过来意味着未赋值的响应将回退同步请求。如果你想让这些请求并发,你可以在数组存储相应的反应:

1 2 3 4 5 6 7 8
美元反应[]=美元客户端- >请求(“职位”,“https://.../path1”);美元反应[]=美元客户端- >请求(“职位”,“https://.../path2”);/ /……/ /这条线将触发所有响应存储在数组的析构函数;/ /他们将完成并发情况下,将抛出一个异常/ /返回状态码300 - 599范围内设置(美元反应);

这种行为在销毁时都是组件的故障保险设计的一部分。没有错误将注意:如果你不编写代码来处理错误,异常在需要的时候会通知你。另一方面,如果你写错误处理代码(通过调用$响应- > getStatusCode ()从这些回退机制),您将选择退出剩下的析构函数不会有什么要做。

并发请求

由于反应懒惰,总是同时管理请求。足够快的网络上,下面的代码使得379个请求在不到半秒当旋度是用:

1 2 3 4 5 6 7 8 9 10
美元反应= [];(美元=0;美元<379年;+ +美元){美元uri=“https://http2.akamai.com/demo/tile- i.png美元”;美元反应[]=美元客户端- >请求(“得到”,美元uri);}foreach(美元反应作为美元响应){美元内容=美元响应- >getContent ();/ /……}

正如你所读到第一个for循环,发出请求,但没有消费。所需的技巧当并发:请求首先被发送,应该读。这将允许客户端代码来监控所有挂起的请求而等待一个特定的一个,在每个迭代完成的上述“foreach循环。

请注意

并发请求的最大数量,您可以执行取决于您的机器的资源(例如,操作系统可能会限制数量的同时读取的文件存储证书文件)。让你的要求分批来避免这些问题。

多路复用的反应

如果你再看看上面的代码片段中,读取响应请求的顺序。但也许第二反应1日之前回来吗?完全异步操作需要能够处理在他们回来的响应。

为了这样做,流()HTTP客户端方法接受一个响应监控列表。正如前面提到的以前,这个方法块,因为他们从网络到收益率反应。通过替换“foreach”与这一个片段,变得完全异步的代码:

1 2 3 4 5 6 7 8 9 10 11 12
foreach(美元客户端- >流(美元反应)作为美元响应= >美元){如果(美元- >isFirst ()) {/ /头刚美元的反应/ / $响应- > getHeaders()现在是一个非阻塞调用}elseif(美元- >isLast ()) {/ /响应美元刚刚完成的全部内容/ / $响应- > getContent()现在是一个非阻塞调用}其他的{/ / $块- > getContent()将返回一个块/ /响应的身体刚}}

提示

使用user_data选择结合$响应- > getInfo (“user_data”)跟踪反应的身份在foreach循环。

处理网络超时

该组件允许处理请求和响应超时。

DNS解析超时发生时如需要太多的时间,当TCP连接不能打开在给定的时间预算,或者当响应内容停顿太久。这可以配置了超时请求选项:

1 2 3
/ /一个TransportExceptionInterface将如果没有公布/ /发生的2.5秒当访问$响应美元响应=美元客户端- >请求(“得到”,“https://..”。,(“超时”= >2.5]);

default_socket_timeout如果使用PHP ini设置没有设置的选项。

选项可以使用第二个参数的覆盖流()方法。这允许监控多个反应时和应用超时的一群。如果所有响应给定时间变得不活跃,将产生一个特殊的块的方法isTimeout ()将返回真正的:

1 2 3 4 5
foreach(美元客户端- >流(美元反应,1.5)作为美元响应= >美元){如果(美元- >isTimeout ()) {/ /响应过期超过美元1.5秒}}

超时并不一定是一个错误:你可以决定再次流响应,得到剩余的内容可能会回来在一个新的超时,等等。

提示

通过0因为超时允许监控以非阻塞方式的反应。

请注意

超时控制人愿意等多久虽然HTTP事务是空闲的。大反应能持续只要需要完成,只要他们保持活跃在转移和从不停顿超过指定。

使用max_duration选项来限制一个完整的请求/响应可以持续的时间。

处理网络故障

网络错误(断管、DNS解析失败,等等)抛出的实例TransportExceptionInterface

首先,你不喜欢处理:让泡沫到通用的异常处理错误堆栈在大多数用例可能是真的好。

如果你想处理它们,这就是你需要知道的:

捕获错误,您需要包装要求$端- >请求()而且任何方法调用返回的响应。这是因为反应是懒惰的,所以当调用如网络错误可以发生。getStatusCode ():

1 2 3 4 5 6 7 8 9 10 11
使用欧宝娱乐app下载地址\合同\HttpClient\异常\TransportExceptionInterface;/ /……试一试{/ /可以把两行美元响应=美元客户端- >请求(/ *……* /);美元=美元响应- >getHeaders ();/ /……}(TransportExceptionInterface美元e){/ /……}

请注意

因为$响应- > getInfo ()非阻塞,它不应该扔掉的设计。

多路复用的反应时,你可以通过捕捉单个流处理错误TransportExceptionInterface在foreach循环:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
foreach(美元客户端- >流(美元反应)作为美元响应= >美元){试一试{如果(美元- >isTimeout ()) {/ /……决定要做什么当一个超时/ /如果你想要停止饱一个超时的响应,不要错过/ /调用$响应- >取消()或响应的析构函数/ /将试图完成它一次}elseif(美元- >isFirst ()) {/ /如果你想检查状态码,你必须做它的时候/ /第一块到达时,使用$响应- > getStatusCode ();/ /如果不这么做可能会触发一个HttpExceptionInterface}elseif(美元- >isLast ()) {/ /……做一些美元反应}}(TransportExceptionInterface美元e){/ /……}}

缓存请求和响应

此组件提供了一个CachingHttpClient修饰符,允许缓存响应和服务下一个请求的本地存储。实现利用了HttpCache类引擎盖下面这样HttpKernel组件需要安装在您的应用程序:

1 2 3 4 5 6 7 8 9 10
使用欧宝娱乐app下载地址\组件\HttpClient\CachingHttpClient;使用欧宝娱乐app下载地址\组件\HttpClient\HttpClient;使用欧宝娱乐app下载地址\组件\HttpKernel\HttpCache\商店;美元商店=存储(' /路径/ /缓存/存储/ ');美元客户端= HttpClient::create ();美元客户端=CachingHttpClient (美元客户端,美元商店);/ /这不会打击网络如果资源已经在缓存中美元响应=美元客户端- >请求(“得到”,“https://example.com/cacheable-resource”);

CachingHttpClient接受一个第三个参数设置的选项HttpCache

接收服务器发送的事件

服务器发送的事件是一个互联网的标准用来推动数据的web页面。它是建立在一个JavaScript APIEventSource对象,该听一些URL发送的事件。一连串的事件数据(服务文本/事件流MIME类型)使用以下格式:

1 2 3 4 5 6
数据:这是第一个消息。数据:这是第二个消息,它数据:有两条线。数据:这是第三个消息。

欧宝娱乐app下载地址Symfony的HTTP客户端提供了一个消费EventSource实现这些服务器发送的事件。使用EventSourceHttpClient包装你的HTTP客户端,打开一个连接到服务器的响应文本/事件流内容类型和消费流如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21日22日23日24日25
使用欧宝娱乐app下载地址\组件\HttpClient\\ServerSentEvent;使用欧宝娱乐app下载地址\组件\HttpClient\EventSourceHttpClient;/ /第二个可选参数的重新连接的时间秒数(默认= 10)美元客户端=EventSourceHttpClient (美元客户端,10);美元=美元客户端- >连接(“https://localhost: 8080 /事件”);(美元){foreach(美元客户端- >流(美元,2)作为美元r= >美元){如果(美元- >isTimeout ()) {/ /……继续;}如果(美元- >isLast ()) {/ /……返回;}/ /这是一个特殊ServerSentEvent块推消息如果(美元运算符ServerSentEvent) {/ /做一些与服务器事件……}}}

互操作性

与四个不同的抽象组件是可互操作的HTTP客户端:欧宝娱乐app下载地址Symfony的合同,PSR-18,HTTPlugv1 / v2和原生PHP流。如果您的应用程序使用的库需要的组件是兼容的。他们也从中受益自动装配的别名框架包使用。

如果你是写作或维护一个库,使HTTP请求,你可以从任何特定的HTTP客户端实现解耦通过编码对Symfony合同(推荐),PSR-18或HTTPlug v2。欧宝娱乐app下载地址

欧宝娱乐app下载地址Symfony的合同

中发现的接口欧宝娱乐app下载地址symfony / http-client-contracts包定义主抽象实现的组件。它的入口点HttpClientInterface。这是你所需要的接口需要针对当客户端代码:

1 2 3 4 5 6 7 8 9 10 11 12 13
使用欧宝娱乐app下载地址\合同\HttpClient\HttpClientInterface;MyApiLayer{私人美元客户端;公共函数__construct(HttpClientInterface美元客户端){美元- >客户=美元客户端;}/ / […]}

上面提到的所有请求选项(例如超时管理)也在文字中定义的接口,以便任何兼容的实现(如该组件)提供保证。这是一个主要的区别与其他抽象,提供所有相关运输本身。

Symfony合同涵盖的另一个主要特性是异步/多路复用,前面部分所描述的。欧宝娱乐app下载地址

PSR-18和PSR-17

这个组件实现了PSR-18通过(HTTP客户端)规范Psr18Client类,它是一个适配器将Symfony欧宝娱乐app下载地址HttpClientInterface成一个PSR-18ClientInterface。这个类也实现了相关的方法PSR-17缓解创建请求对象。

使用它,你需要psr / http客户端包和一个PSR-17实现:

1 2 3 4 5 6 7 8 9 10
#安装PSR-18 ClientInterface美元作曲家需要psr / http客户端#安装响应和流的高效实现工厂#与自动装配Symfony Flex提供的别名欧宝娱乐app下载地址美元作曲家需要nyholm / psr7#此外,安装php-http /发现包自动发现#任何已安装实现共同的供应商:#作曲家需要php-http /发现

现在你可以与PSR-18客户端发出HTTP请求如下:

  • 框架的使用
  • 独立使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
使用Psr\Http\客户端\ClientInterface;欧宝娱乐app下载地址{私人美元客户端;公共函数__construct(ClientInterface美元客户端){美元- >客户=美元客户端;}公共函数getAvailableVersions():数组{美元请求=美元- >客户端- >都会(“得到”,“https://欧宝娱乐app下载地址www.oldmanjams.com/versions.json”);美元响应=美元- >客户端- >sendRequest (美元请求);返回json_decode (美元响应- >getBody ()- >getContents (),真正的);}}

HTTPlug

HTTPlugv1规范发布之前PSR-18和取代它。因此,你不应该在新编写的代码中使用它。库的组件仍可互操作的要求,谢谢HttplugClient类。类似于Psr18Client实现PSR-17相关部分,HttplugClient还实现了在相关定义的工厂方法php-http /消息工厂包中。

1 2 3 4 5 6 7 8 9
#假设php-http / httplug已经要求你想要的自由使用#安装响应和流的高效实现工厂#与自动装配Symfony Flex提供的别名欧宝娱乐app下载地址美元作曲家需要nyholm / psr7#此外,安装php-http /发现包自动发现#任何已安装实现共同的供应商:#作曲家需要php-http /发现

假设你想要实例化一个类的构造函数后,要求HTTPlug依赖性:

1 2 3 4 5 6 7 8 9 10 11 12 13
使用Http\客户端\HttpClient;使用Http\消息\RequestFactory;使用Http\消息\StreamFactory;SomeSdk{公共函数__construct(HttpClient美元httpClient,RequestFactory美元requestFactory,StreamFactory美元streamFactory)/ / […]}

因为HttplugClient实现了三个接口,您可以使用它:

1 2 3 4
使用欧宝娱乐app下载地址\组件\HttpClient\HttplugClient;美元httpClient=HttplugClient ();美元apiClient=SomeSdk (美元httpClient,美元httpClient,美元httpClient);

如果你想与承诺,HttplugClient还实现了HttpAsyncClient接口。使用它,你需要安装guzzlehttp /承诺包:

1
美元作曲家需要guzzlehttp /承诺

那么你准备好了:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30
使用Psr\Http\消息\ResponseInterface;使用欧宝娱乐app下载地址\组件\HttpClient\HttplugClient;美元httpClient=HttplugClient ();美元请求=美元httpClient- >都会(“得到”,“https://my.api.com/”);美元承诺=美元httpClient- >sendAsyncRequest (美元请求)- >然后(函数(ResponseInterface美元响应){回声“有状态”美元响应- >getStatusCode ();返回美元响应;},函数(\ Throwable美元异常){回声的错误:美元异常- >getMessage ();美元异常;});/ /你完成发送多个请求后,/ /同时你必须等待他们完成/ /等待一个特定的承诺解决,同时监控美元响应=美元承诺- >wait ();/ /最大1秒等待等待承诺的决心美元httpClient- >等待(1.0);/ /等待所有剩余的承诺来解决美元httpClient- >wait ();

原生PHP流

反应实现ResponseInterface可以把原生PHP流createResource ()。这允许使用原生PHP流需要的地方:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
使用欧宝娱乐app下载地址\组件\HttpClient\HttpClient;使用欧宝娱乐app下载地址\组件\HttpClient\响应\StreamWrapper;美元客户端= HttpClient::create ();美元响应=美元客户端- >请求(“得到”,“https://欧宝娱乐app下载地址www.oldmanjams.com/versions.json”);美元streamResource= StreamWrapper::createResource (美元响应,美元客户端);/ /另外,与上次相反,这个回报/ /资源seekable和潜在stream_select()能够身美元streamResource=美元响应- >toStream ();回声stream_get_contents (美元streamResource);/ /输出响应的内容/ /以后如果你需要,你可以访问的响应流美元响应= stream_get_meta_data (美元streamResource)[“wrapper_data”]- >getResponse ();

可扩展性

如果你想扩展的行为基本HTTP客户端,您可以使用装饰服务:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21日22日23日24日25
MyExtendedHttpClient实现了HttpClientInterface{私人美元decoratedClient;公共函数__construct(HttpClientInterface美元decoratedClient= null){美元- >decoratedClient =美元decoratedClient? ?HttpClient::create ();}公共函数请求(字符串美元方法、字符串美元url数组,美元选项= []):ResponseInterface{/ /流程和/或改变美元的方法,根据需要url和/或选择美元美元响应=美元- >decoratedClient- >请求(美元方法,美元url,美元选项);/ /如果你调用任何方法在响应,美元的HTTP请求/ /不会异步;下面是一个更好的方法返回美元响应;}公共函数(美元反应、浮点数美元超时= null):ResponseStreamInterface{返回美元- >decoratedClient- >流(美元反应,美元超时);}}

这样的装饰是有用的在处理请求的参数的情况下就足够了。通过装饰on_progress选择,你甚至可以实现基本的监视响应。然而,由于调用响应的方法部队同步操作,这样做在里面请求()将异步。

解决方案是也装修响应对象本身。TraceableHttpClientTraceableResponse是很好的例子作为起点。

为了帮助写作更高级的响应处理器,组件提供了一个AsyncDecoratorTrait。这个特征允许处理流的块回来从网络:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
MyExtendedHttpClient实现了HttpClientInterface{使用AsyncDecoratorTrait;公共函数请求(字符串美元方法、字符串美元url数组,美元选项= []):ResponseInterface{/ /流程和/或改变美元的方法,根据需要url和/或选择美元美元passthru=函数(ChunkInterface美元,AsyncContext美元上下文){/ /块做你想做的事情,例如分裂/ /在小块,它们分组,跳过一些,等等。收益率美元;};返回AsyncResponse (美元- >客户端,美元方法,美元url,美元选项,美元passthru);}}

因为已经实现了一个构造函数和特征流()方法,您不需要添加它们。的请求()方法仍应被定义;它将返回一个AsyncResponse

自定义处理块应该发生passthru美元:这个发电机就是你需要编写逻辑。它将要求每个块产生的潜在客户。一个passthru美元,只会毫无作用收益率块美元;。你也可以产生修改块,块分割成许多的收益率几次,甚至完全跳过一块发出返回;而不是屈服。

为了控制流,块passthru收到AsyncContext作为第二个参数。这个上下文对象的方法来读取的当前状态的反应。它还允许改变的响应流方法来创建新的内容块,暂停,取消流,改变响应的信息,取代当前请求的另一个块passthru本身或改变。

检查测试用例实现AsyncDecoratorTraitTest可能是一个好的开始获得更好地了解各种工作的例子。这里是用例,它模拟:

  • 重试失败的请求;
  • 发送一个起飞前的请求,如用于身份验证的需求;
  • subrequests问题,包括其内容在主反应的身体。

的逻辑AsyncResponse有许多安全检查,将抛出一个LogicException如果块passthru不正确的行为;例如,如果一块后产生isLast ()一个,或者如果一个内容块之前isFirst ()一个,等等。

测试

该组件包括MockHttpClientMockResponse类用于测试,不应使实际的HTTP请求。等测试可以是有用的,他们会跑得更快,产生一致的结果,因为它们不依赖于外部服务。不做实际的HTTP请求不需要担心服务上网或请求改变状态,例如删除资源。

MockHttpClient实现了HttpClientInterface,就像任何实际的HTTP客户端组件。当你type-hintHttpClientInterface代码会接受真正的客户端外部测试,而取而代之MockHttpClient在测试。

请求方法是用在MockHttpClient,它将提供的MockResponse。有一些方法来使用它,如下所述。

HTTP客户端和响应

第一种方法的使用MockHttpClient是通过对其构造函数的列表。这将是产生在请求:

1 2 3 4 5 6 7 8 9 10 11 12
使用欧宝娱乐app下载地址\组件\HttpClient\MockHttpClient;使用欧宝娱乐app下载地址\组件\HttpClient\响应\MockResponse;美元反应= (MockResponse (美元界面,美元info1),MockResponse (美元body2,美元info2),);美元客户端=MockHttpClient (美元反应);/ /响应返回的顺序传递给MockHttpClient美元response1=美元客户端- >请求(“……”);/ /返回响应[0]美元美元response2=美元客户端- >请求(“……”);/ /返回$响应[1]

另一种方式使用MockHttpClient是通过一个回调时动态地生成反应叫做:

1 2 3 4 5 6 7 8 9
使用欧宝娱乐app下载地址\组件\HttpClient\MockHttpClient;使用欧宝娱乐app下载地址\组件\HttpClient\响应\MockResponse;美元回调=函数(美元方法,美元url,美元选项){返回MockResponse (“……”);};美元客户端=MockHttpClient (美元回调);美元响应=美元客户端- >请求(“……”);/ /调用回调到得到响应

提示

而不是使用第一个参数,还可以设置(列表)反应或使用回调setResponseFactory ()方法:

1 2 3 4 5 6 7
美元反应= (MockResponse (美元界面,美元info1),MockResponse (美元body2,美元info2),);美元客户端=MockHttpClient ();美元客户端- >setResponseFactory (美元反应);

如果你需要测试响应HTTP状态码不同于200年定义http_code选择:

1 2 3 4 5 6 7 8 9
使用欧宝娱乐app下载地址\组件\HttpClient\MockHttpClient;使用欧宝娱乐app下载地址\组件\HttpClient\响应\MockResponse;美元客户端=MockHttpClient ([MockResponse (“……”,(“http_code”= >500年]),MockResponse (“……”,(“http_code”= >404年))));美元响应=美元客户端- >请求(“……”);

模拟客户端提供的反应不需要的实例MockResponse。任何类实现ResponseInterface将(如工作。$ this - > createMock (ResponseInterface::类))。

然而,使用MockResponse允许模拟分块反应和超时:

1 2 3 4 5 6 7 8
美元身体=函数(){收益率“你好”;/ /空字符串变成超时,这样他们很容易测试收益率;收益率“世界”;};美元mockResponse=MockResponse (美元身体());

最后,您还可以创建一个调用或iterable类产生的反应和使用它作为一个回调功能测试:

1 2 3 4 5 6 7 8 9 10 11 12 13 14
名称空间应用程序\测试;使用欧宝娱乐app下载地址\组件\HttpClient\响应\MockResponse;使用欧宝娱乐app下载地址\合同\HttpClient\ResponseInterface;MockClientCallback{公共函数__invoke(字符串美元方法、字符串美元url数组,美元选项= []):ResponseInterface{/ /加载夹具文件或生成数据/ /……返回MockResponse (美元数据);}}

然后配置Symfony使用回调欧宝娱乐app下载地址:

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8 9
#配置/ services_test.yaml服务:#……应用\ \ MockClientCallback测试:~#配置/包/测试/ framework.yaml框架:http_client:mock_response_factory:应用\ \ MockClientCallback测试

测试请求数据

MockResponse类提供了一些辅助方法来测试要求:

  • getRequestMethod ()——返回HTTP方法;
  • getRequestUrl ()——返回的URL请求将被发送到;
  • getRequestOptions ()请求,返回一个数组,其中包含其他信息,如标题,查询参数,正文内容等。

使用的例子:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
美元mockResponse=MockResponse (,(“http_code”= >204年]);美元httpClient=MockHttpClient (美元mockResponse,“https://example.com”);美元响应=美元httpClient- >请求(“删除”,“api /文章/ 1337”,(“头”= > [“接受:* / *”,“授权:基本YWxhZGRpbjpvcGVuc2VzYW1l”、]]);美元mockResponse- >getRequestMethod ();/ /返回“删除”美元mockResponse- >getRequestUrl ();/ /返回“https://example.com/api/article/1337”美元mockResponse- >getRequestOptions () (“头”];/ /返回(“接受:* / *”、“授权:基本YWxhZGRpbjpvcGVuc2VzYW1l”)

完整的示例

下面的独立的例子演示了一种使用HTTP客户端和测试它在真实的应用程序:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
/ / ExternalArticleService.php使用欧宝娱乐app下载地址\合同\HttpClient\HttpClientInterface;最后ExternalArticleService{私人HttpClientInterface美元httpClient;公共函数__construct(HttpClientInterface美元httpClient){美元- >httpClient =美元httpClient;}公共函数createArticle(数组美元requestData):数组{美元requestJson= json_encode (美元requestData,JSON_THROW_ON_ERROR);美元响应=美元- >httpClient- >请求(“职位”,“api /文章”,(“头”= > [“application / json内容类型:,接受:application / json的),“身体”= >美元requestJson]);如果(201年= = !美元响应- >getStatusCode ()) {异常(“比预期的响应状态代码是不同的。”);}/ /……其他检查美元responseJson=美元响应- >getContent ();美元responseData= json_decode (美元responseJson,真正的,512年,JSON_THROW_ON_ERROR);返回美元responseData;}}/ / ExternalArticleServiceTest.php使用PHPUnit)\框架\TestCase;使用欧宝娱乐app下载地址\组件\HttpClient\MockHttpClient;使用欧宝娱乐app下载地址\组件\HttpClient\响应\MockResponse;最后ExternalArticleServiceTest扩展TestCase{公共函数testSubmitData():无效{/ /安排美元requestData= (“标题”= >“测试使用Symfony H欧宝娱乐app下载地址TTP客户端”];美元expectedRequestData= json_encode (美元requestData,JSON_THROW_ON_ERROR);美元expectedResponseData= (“id”= >12345年];美元mockResponseJson= json_encode (美元expectedResponseData,JSON_THROW_ON_ERROR);美元mockResponse=MockResponse (美元mockResponseJson,(“http_code”= >201年,“response_headers”= > [“application / json内容类型:)));美元httpClient=MockHttpClient (美元mockResponse,“https://example.com”);美元服务=ExternalArticleService (美元httpClient);/ /行为美元responseData=美元服务- >createArticle (美元requestData);/ /维护自我::assertSame (“职位”,美元mockResponse- >getRequestMethod ());自我::assertSame (“https://example.com/api/article”,美元mockResponse- >getRequestUrl ());自我::assertContains (“application / json内容类型:,美元mockResponse- >getRequestOptions () (“头”]);自我::assertSame (美元expectedRequestData,美元mockResponse- >getRequestOptions () (“身体”]);自我::assertSame (美元responseData,美元expectedResponseData);}}
这项工作,包括代码示例,许可下Creative Commons冲锋队3.0许可证。
欧宝娱乐app下载地址Symfony 6.2支持通过苏禄人
欧宝娱乐app下载地址Symfony 6.2支持通过Les-Tilleuls.coop