Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Buffpie's avatar

How to use the HTTP facade in a Job / Schedule

Hello,

I've been trying to make use of laravel's Jobs and Queues in order to sync the data I can get from an external API on my application.

To do so, I tried to implement a Job however, when I tried to call my sync method with the HTTP::geat() I got the following error :

 GuzzleHttp\Exception\ConnectException: cURL error 28: Operation timed out after 10001 milliseconds with 0 out of 0 bytes received (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://.../stconfig/api/v1/components in /var/www/html/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php:210

To fix it, I was able to do so by using the HTTP::get() in the __conscruct() of the Job, which seemed to add the data to the Job's payload.

However, now that's I'm trying to make a recurring schedule, I'm getting this error once more no matter what I try. Here is what I tried which didn't work :

  • Using a job that calls the method with the HTTP::get()
  • Using a job that calls the HTTP::get() in the __construct()
  • Calling the HTTP::get() from the schedule->call()
  • Using the schedule on the sync connection (rather than database)
  • Increasing the timeout of the curl and job (but anyways they should be almost instant so no matter what it shouldn't time out)

Overall I'm pretty lost so if anyone has an idea, I'm all ears for it :)

Here are some code extracts that can help illustrate my problem :

<?php

namespace App\Jobs;

use App\Services\ComponentService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Throwable;

class SynchroStconfig implements ShouldQueue, ShouldBeUnique
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $response;

    public function __construct()
    {
        $baseURL = config('myhub.tiles.0.tiles.0.link');
        $this->response = Http::withHeaders(
            [ 'Accept' => 'application/json']
        )->timeout(30)
            ->get("{$baseURL}api/v1/components")
            ->object();
    }

    public function handle()
    {
        ComponentService::new()->synchroStconfig($this->response);
    }

    public function failed(Throwable $exception)
    {
        Log::error("SynchroStconfig job failed - {$exception}");
    }
}
$schedule->job((new SynchroStconfig)->onConnection('sync'))
            ->cron("* * * * *");

$schedule->job(new SynchroStconfig)
            ->cron("* * * * *");

$schedule->call(
            function () {
                $baseURL = config('myhub.tiles.0.tiles.0.link');
                $response = Http::withHeaders(
                    ['Accept' => 'application/json']
                )->timeout(30)
                    ->get("{$baseURL}api/v1/components")
                    ->object();

                ComponentService::new()->synchroStconfig($response);
            }
        )->cron("* * * * *");
0 likes
12 replies
LaryAI's avatar
Level 58

The error you are encountering is a cURL timeout error. This error occurs when the HTTP request takes longer than the specified timeout value. To fix this issue, you can try the following solutions:

  1. Increase the timeout value: You can increase the timeout value in your HTTP request to allow more time for the request to complete. For example, you can set the timeout to 60 seconds by using the timeout method:
$this->response = Http::withHeaders(['Accept' => 'application/json'])
    ->timeout(60)
    ->get("{$baseURL}api/v1/components")
    ->object();
  1. Use a try-catch block: Wrap your HTTP request in a try-catch block to catch any exceptions that may occur. This will allow you to handle the exception gracefully and prevent it from crashing your application. For example:
try {
    $this->response = Http::withHeaders(['Accept' => 'application/json'])
        ->timeout(60)
        ->get("{$baseURL}api/v1/components")
        ->object();
} catch (\Exception $e) {
    // Handle the exception
    Log::error("HTTP request failed: {$e->getMessage()}");
}
  1. Check your network connection: Ensure that your server has a stable internet connection and can access the external API. You can try pinging the API URL from your server to check for any network issues.

  2. Verify the API URL: Double-check the API URL to ensure that it is correct and accessible. Make sure there are no typos or missing parameters in the URL.

  3. Test the API request outside of the job/schedule: Try making the API request outside of the job or schedule to see if it works correctly. This will help isolate the issue and determine if it is related to the job/schedule or the API itself.

Additionally, make sure you have the Guzzle HTTP client installed in your Laravel project. You can install it by running the following command:

composer require guzzlehttp/guzzle

Remember to import the Http facade at the top of your file:

use Illuminate\Support\Facades\Http;

I hope this helps! Let me know if you have any further questions.

Snapey's avatar

forget Laravel. How long does the request take if you use Postman / RapidAPI etc

Buffpie's avatar

@Snapey To help with a bit of clarifications with that Http::get() request :

  • It works fine if I use it as is in the controler or a service (no jobs or schedules)
  • It works fine if I use it in a job's handle ONLY if I "dispatchAfterResponse" (dispatch itself won't work, same timeout)
  • It works fine if I use it in a job's __construct() if I dispatch the job (the get result goes into the payload in the database it seems + same timeout if I use the Http::get() in the job's handle)
  • It doesn't work no matter where I put a Http::get() for a schedule (in the Kernel.php), no matter which previous job I try to use or if I try to call it with the call() function

If you need any more clarifications or info about this issue please tell me and I'll try to get back to you with it as fast as possible.

Buffpie's avatar

@Snapey no I'm not.

The production and devs instances I'm using are on servers. I wasn't the one to set this up but from what I understand, I use a docker-compose to create a PHP and nginx image on which I can simply connect by opening a port.

In any case, I don't use the artisan serve command.

Buffpie's avatar

@krisi_gjika I use the .env file in my container by mounting them when I run my docker-compose

Ex for the php image :

volumes:
            - "./src:/web"
            - "./etc/php/php.ini:/usr/local/etc/php/conf.d/php.ini"
            - "/etc/pki/tls/cert.pem:/usr/local/etc/php/conf.d/cert.pem"
            - "/opt/myhub/.env:/web/.env"
            - "/etc/hosts:/etc/hosts" 	
krisi_gjika's avatar

@Buffpie what I mean is that if your scheduled job depends on environment variables, you need to load them manually, since cron does not load environment variables. In that case one option would be to export your environment variables env >> /etc/environment

Buffpie's avatar

@krisi_gjika oh ok I see what you mean. However I don't think the .env should be a problem since :

  • I am able to run the job with the HTTP::get() in the __construct() and other facades (like Log)
  • I am unable to run the job with the Http::get() in the handle() but I can use other facades (like Log)

That's why I don't think the problem lies with the .env but rather how Laravel jobs work and if it's even possible to use the HTTP facade from the handle of a job (how the payload seems to work / be used).

krisi_gjika's avatar

@Buffpie the HTTP:: in your constructor is being called from your application, but HTTP:: in your handle is being called by the queued job handler. It is possible that $baseURL is not what you think, or at least is not the same in these two cases. I would start by logging the $baseURL in both cases and go from there.

Buffpie's avatar

@krisi_gjika the $baseURL is set from a config file but just in case I tried using a Log::info() and hard coding it and anyways I get the same cURL exception.

Please or to participate in this conversation.