重用 Symfony 的 HTTP 客户端会导致错误,但使用新实例执行请求会按预期工作
Reusing Symfony's HTTP Client results in error, but executing the request with a new instance works as expected
我的系统需要通过外部服务进行身份验证(无论如何我都无法控制),并且身份验证需要两个非常短的 HTTP 请求(我在第一个请求中获得的令牌在 2 秒后过期,我必须使用它来完成身份验证过程)。
所以我基本上是这样做的:
// create client
$client = HttpClient::create();
$baseUrl = "https://example.com/webservice.php";
$username = "foo";
$token = "foobarbaz";
// first request
$tokenResponse = $client->request( Method::GET, $baseUrl . '?operation=getchallenge&username=' . $username );
$decoded = $tokenResponse->toArray();
// second request
$loginResponse = $client->request( Method::POST, $this->baseUrl, [
'body' => [
'operation' => 'login',
'username' => $username,
'accessKey' => md5( $decoded['result']['token'] . $token ),
],
]
);
$sessionData = $loginResponse->toArray();
这样做,我得到一个异常(TransportExceptionInterface
):
Failed sending data to the peer for "https://example.com/webservice.php"
但是,如果我不使用相同的 $client
,而是实例化一个新的 ($client2 = HttpClient::create();
),然后使用 那个 来发出第二个请求,无需对代码进行任何其他更改,它将完美运行。
我的猜测是,这与 HTTP 客户端使用的默认请求并发性有关,但我检查了 HttpClientInterface
上的 docs and the options available,但我还没有改变客户端行为以一种不需要我创建新实例的方式(也不需要增加错误日志记录的详细程度)。
我安装了 cURL 扩展,因此正在创建的客户端是 CurlHttpClient
而不是 NativeHttpClient
。
有没有办法解决这个问题,而不必创建新的客户端实例?
这是文档所说的。
Even when doing regular synchronous calls, this design allows keeping
connections to remote hosts open between requests, improving
performance by saving repetitive DNS resolution, SSL negotiation, etc.
To leverage all these design benefits, the cURL extension is needed.
为了使用 php 流,该示例说明您按如下方式使用 NativeClient:
use Symfony\Component\HttpClient\CurlHttpClient;
use Symfony\Component\HttpClient\NativeHttpClient;
// uses native PHP streams
$client = new NativeHttpClient();
// uses the cURL PHP extension
$client = new CurlHttpClient();
这样你就可以 select 没有框架的特定客户端让你使用 curl 客户端。
获得令牌后,关闭连接并从同一个客户端创建一个新连接,这将确保您使用相同的客户端 object 但启动新的连接要求,模仿服务器要求的行为以便验证。
在解析之前检查服务器响应总是好的 body。请检查服务器是否已发送带有令牌的 200 响应并分支出您的逻辑。尝试捕获或检查 headers 始终是错误处理的奖励和良好实践。
我的系统需要通过外部服务进行身份验证(无论如何我都无法控制),并且身份验证需要两个非常短的 HTTP 请求(我在第一个请求中获得的令牌在 2 秒后过期,我必须使用它来完成身份验证过程)。
所以我基本上是这样做的:
// create client
$client = HttpClient::create();
$baseUrl = "https://example.com/webservice.php";
$username = "foo";
$token = "foobarbaz";
// first request
$tokenResponse = $client->request( Method::GET, $baseUrl . '?operation=getchallenge&username=' . $username );
$decoded = $tokenResponse->toArray();
// second request
$loginResponse = $client->request( Method::POST, $this->baseUrl, [
'body' => [
'operation' => 'login',
'username' => $username,
'accessKey' => md5( $decoded['result']['token'] . $token ),
],
]
);
$sessionData = $loginResponse->toArray();
这样做,我得到一个异常(TransportExceptionInterface
):
Failed sending data to the peer for "https://example.com/webservice.php"
但是,如果我不使用相同的 $client
,而是实例化一个新的 ($client2 = HttpClient::create();
),然后使用 那个 来发出第二个请求,无需对代码进行任何其他更改,它将完美运行。
我的猜测是,这与 HTTP 客户端使用的默认请求并发性有关,但我检查了 HttpClientInterface
上的 docs and the options available,但我还没有改变客户端行为以一种不需要我创建新实例的方式(也不需要增加错误日志记录的详细程度)。
我安装了 cURL 扩展,因此正在创建的客户端是 CurlHttpClient
而不是 NativeHttpClient
。
有没有办法解决这个问题,而不必创建新的客户端实例?
这是文档所说的。
Even when doing regular synchronous calls, this design allows keeping connections to remote hosts open between requests, improving performance by saving repetitive DNS resolution, SSL negotiation, etc. To leverage all these design benefits, the cURL extension is needed.
为了使用 php 流,该示例说明您按如下方式使用 NativeClient:
use Symfony\Component\HttpClient\CurlHttpClient;
use Symfony\Component\HttpClient\NativeHttpClient;
// uses native PHP streams
$client = new NativeHttpClient();
// uses the cURL PHP extension
$client = new CurlHttpClient();
这样你就可以 select 没有框架的特定客户端让你使用 curl 客户端。
获得令牌后,关闭连接并从同一个客户端创建一个新连接,这将确保您使用相同的客户端 object 但启动新的连接要求,模仿服务器要求的行为以便验证。
在解析之前检查服务器响应总是好的 body。请检查服务器是否已发送带有令牌的 200 响应并分支出您的逻辑。尝试捕获或检查 headers 始终是错误处理的奖励和良好实践。