php - Laravel Defer on API requests - Stack Overflow

时间: 2025-01-06 admin 业界

Is it possible to use defer functions on API requests? I can run defer on my website, but through API is not working at all.

Sample scenario:

// Endpoint accessible through browser 
public function index(Request $request): void
{
    Log::info('Before response sent');
    defer(function () {
        Log::info('Deferred task executed');
    });
    Log::info('After response sent');
}

// Endpoint accessible through API request https://mywebsite/api/something
public function search(Request $request): JsonResponse
{
    Log::info('Before response sent.');
    defer(function () {
        Log::info('Deferred task executed.');
    });
    Log::info('After response sent.');
    
    return response()->json(true);
}

This sample only works when acessing the endpoint through browser. With the API endpoint, by using either tests or Postman, the message Deferred task executed. is never written.

I tried to create a middleware, applied to the API endpoints, in order to make sure the app is terminated so the defer functions execute, but got no luck.

class EnforceDeferForApi
{
    public function handle(Request $request, Closure $next)
    {
        return $next($request);
    }

    public function terminate(Request $request, $response): void
    {
        app()->terminate();
    }
} 

Any solution?

Is it possible to use defer functions on API requests? I can run defer on my website, but through API is not working at all.

Sample scenario:

// Endpoint accessible through browser https://mywebsite.com/something
public function index(Request $request): void
{
    Log::info('Before response sent');
    defer(function () {
        Log::info('Deferred task executed');
    });
    Log::info('After response sent');
}

// Endpoint accessible through API request https://mywebsite/api/something
public function search(Request $request): JsonResponse
{
    Log::info('Before response sent.');
    defer(function () {
        Log::info('Deferred task executed.');
    });
    Log::info('After response sent.');
    
    return response()->json(true);
}

This sample only works when acessing the endpoint through browser. With the API endpoint, by using either tests or Postman, the message Deferred task executed. is never written.

I tried to create a middleware, applied to the API endpoints, in order to make sure the app is terminated so the defer functions execute, but got no luck.

class EnforceDeferForApi
{
    public function handle(Request $request, Closure $next)
    {
        return $next($request);
    }

    public function terminate(Request $request, $response): void
    {
        app()->terminate();
    }
} 

Any solution?

Share Improve this question edited yesterday Linesofcode asked yesterday LinesofcodeLinesofcode 5,88914 gold badges70 silver badges130 bronze badges 6
  • While I understand it not working in tests (since tests may behave differently when interacting with the queue or middleware). I don't see any real reason why it shouldn't work in Postman unless there's an other error happening that is being masked. Does it work in an icognito browser tab, if not maybe there's some sort of dependency on a session? – apokryfos Commented yesterday
  • This should ideally work as defer here is only meant to hold off execution of logging the info in your use case until after a response of true is returned. You can try this out testing your endpoint with Postman, RapidApi or any other api testing platforms. – Olumuyiwa Commented yesterday
  • @apokryfos There's no error whatsoever. Again: this doesn't work on API endpoints, but works on web endpoints. I even called an API endpoint through javascript and same behaviour. It's not related to postman or tests. Give it a try. – Linesofcode Commented yesterday
  • @Olumuyiwa it doesn't work. Read my previous response, it's not related to Postman, nor tests. It doesn't work through conventional javascript too. It's related to how API routes work. – Linesofcode Commented yesterday
  • I’m not a Laravel person, so pardon my ignorance. What is an “API endpoint”, or rather, what’s the difference between it and other endpoints? Does it require a specific content type or another header? Or is it a method other than GET or POST? – Chris Haas Commented yesterday
 |  Show 1 more comment

1 Answer 1

Reset to default 1

Solved.

Forgot to add \Illuminate\Foundation\Http\Middleware\InvokeDeferredCallbacks::class to the array of api in $middlewareGroups » file kernel.php