yiisoft / yii2-httpclient

Yii 2 HTTP client
https://www.yiiframework.com
BSD 3-Clause "New" or "Revised" License
430 stars 157 forks source link

Timeout setting is invalid #243

Closed harusakura924 closed 8 months ago

harusakura924 commented 8 months ago

What steps will reproduce the problem?

  1. Create a sleep(80); method in the controller
    public function actionTimeOut()
    {
       sleep(80); // Sleep for 20 seconds
       return '!!!!!TimeOut!!!!!';
    }
  2. Use yii\httpclient\Client to create a Request and set Options CURLOPT_TIMEOUT => 10 and CURLOPT_CONNECTTIMEOUT => 5

    header('content-Type: text/plain; charset=utf-8');
    try {
      $client = new \yii\httpclient\Client();
      $request = $client->createRequest()
         ->setMethod('GET')
         ->setUrl(Url::to(['time-out'], 'https'))
         ->setOptions([
            CURLOPT_TIMEOUT => 10, // total timeout
            CURLOPT_CONNECTTIMEOUT => 5, // Connection timeout
         ]);
      \yii\helpers\VarDumper::dump($request->toString(), $depth=10, $highlight=false); echo "\n";
    
      $response = $request->send();
      \yii\helpers\VarDumper::dump($response, $depth=10, $highlight=false); echo "\n";
    } catch (\yii\httpclient\Exception $e) {
      \yii\helpers\VarDumper::dump('time out', $depth=10, $highlight=false); echo "\n";
      \yii\helpers\VarDumper::dump($e, $depth=10, $highlight=false); echo "\n";
    }
    exit();
  3. You will wait almost 80 seconds.

What's expected?

If you use php curl.

$url = Url::to(['time-out'], 'https');

$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($curl, CURLOPT_TIMEOUT, 10);

$response = curl_exec($curl);
$curl_errno = curl_errno($curl);
$curl_error = curl_error($curl);

if ($curl_errno) {
    echo "cURL error:{$curl_error}\n";
} else {
    echo "cURL success:{$response}\n";
}

curl_close($curl);

You will get the following message within 10 seconds.

cURL error:Operation timed out after 10001 milliseconds with 0 out of -1 bytes received

What do you get instead?

abnormal waiting.

Additional info

Q A
Yii version 2.0.47
Yii HTTP Client version 2.2.13.0
PHP version 5.4
Operating system CentOS 7
harusakura924 commented 8 months ago

In addition, it works for me to use the following method, but I still can't get the connection timeout message. If I use $response->getStatusCode(), you will only get Unable to get status code: referred header information is missing. , you know there is a problem, but you don’t know where the problem is. It may be a client setting error, it may be a network problem...

header('content-Type: text/plain; charset=utf-8');
try
{
    $client = new \yii\httpclient\Client();
    $request = $client->createRequest()
        ->setMethod('GET')
        ->setUrl(Url::to(['time-out'], 'https'))
        ->setOptions([
            'timeout' => 5,
        ]);
    \yii\helpers\VarDumper::dump($request->toString(), $depth=10, $highlight=false); echo "\n";

    $response = $request->send();
    \yii\helpers\VarDumper::dump('ok', $depth=10, $highlight=false); echo "\n";
    // time out, Unless you call isOk or statusCode, you will not be told time out.
    \yii\helpers\VarDumper::dump($response, $depth=10, $highlight=false); echo "\n";
} catch (\yii\httpclient\Exception $e) {
    \yii\helpers\VarDumper::dump('error', $depth=10, $highlight=false); echo "\n";
    \yii\helpers\VarDumper::dump($e, $depth=10, $highlight=false); echo "\n";
}
exit();
bizley commented 8 months ago

By default client is using StreamTransport instead of CurlTransport as described here so your options don't apply. Is it the case?

harusakura924 commented 8 months ago

By default client is using StreamTransport instead of CurlTransport as described here so your options don't apply. Is it the case?

Thank you for your reminder. I originally used StreamTransport with CURL Options, but it had no effect.

If you use TimeOut of StreamTransport you cannot get the information that the connection was interrupted due to TimeOut, but when I change to CurlTransport I will be able to get the information I want.