laravel / framework

The Laravel Framework.
https://laravel.com
MIT License
32.62k stars 11.03k forks source link

Http client timing out sooner than the timeout option #53564

Closed sts-ryan-holton closed 20 hours ago

sts-ryan-holton commented 3 days ago

Laravel Version

11.30.0

PHP Version

8.3.9

Database Driver & Version

MySQL 8

Description

Recently, I've been getting some Curl 28 errors relating to time outs sooner than the timeout specified on the Http client. This is strange and has been intermittently happening for a few weeks now.

Despite passing a number in to the timeout method, e.g: 25, I'm seeing errors cutting off sooner:

cURL error 28: Operation timed out after 5001 milliseconds with 0 bytes received (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://www.pixiedustdancewear.co.uk

Steps To Reproduce

I have a method that builds up the HTTP client:

/**
 * HTTP type
 *
 * @return object
 */
public function getHttpMonitorResponse($monitor, $timeout)
{
    $url = $monitor->url;

    if (str_contains($url, 'cachebuster={timestamp}')) {
        $timestamp = Carbon::now()->timestamp;
        $url = str_replace('cachebuster={timestamp}', 'cachebuster='.$timestamp, $url);
    }

    $headers = [
        'User-Agent' => 'Mozilla/5.0+(compatible; DomainMonitor/2.0; https://domain-monitor.io/)',
    ];

    $payload = null;

    if ($monitor->http_body) {
        try {
            $payload = json_decode($monitor->http_body, true);
        } catch (\Exception $e) {
        }
    }

    $client = Http::withHeaders($headers)->timeout($timeout);

    // prevent SSL errors when debug is on
    if (config('app.debug')) {
        $client = $client->withOptions([
            'verify' => false,
        ]);
    }

    // set authentication
    $client = match ($monitor->auth_type) {
        'basic' => $client->withBasicAuth($monitor->username, $monitor->password),
        'digest' => $client->withDigestAuth($monitor->username, $monitor->password),
        'token' => $client->withToken($monitor->password),
        default => $client,
    };

    // set HTTP method
    $client = match ($monitor->method) {
        'get' => $client->get($url),
        'head' => $client->head($url),
        'delete' => $client->delete($url),
        'post' => $client->post($url, $payload),
        'put' => $client->put($url, $payload),
        'patch' => $client->patch($url, $payload),
        default => $client->get($url),
    };

    return $client;
}
cosmastech commented 3 days ago

My first thought was that withOptions() is overwriting it, but I don't think that's the case. Is there any code not included here that may be modifying the client object?

crynobone commented 3 days ago

Hey there, thanks for reporting this issue.

We'll need more info and/or code to debug this further. Can you please create a repository with the command below, commit the code that reproduces the issue as one separate commit on the main/master branch and share the repository here?

Please make sure that you have the latest version of the Laravel installer in order to run this command. Please also make sure you have both Git & the GitHub CLI tool properly set up.

laravel new bug-report --github="--public"

Do not amend and create a separate commit with your custom changes. After you've posted the repository, we'll try to reproduce the issue.

Thanks!

sts-ryan-holton commented 2 days ago

@cosmastech Not that i can think, I've experienced this in a few projects recently

morloderex commented 1 day ago

Could it not be the connectTimeout that you are hitting in this specific case? Sense pr default they aren't the same and they shouldn't be.

sts-ryan-holton commented 20 hours ago

I'm not setting connect_timeout. Looking at Laravel's code, looks lihe their default value for connect_timeout is 10 seconds, but my error is 5 seconds. I'm passing 25 seconds for the timeout option. In the PendingRequest.php both values are seconds.

So I think there's some bug somewhere here in Laravel?