saloon icon indicating copy to clipboard operation
saloon copied to clipboard

Middleware order not work

Open IgordeOliveira opened this issue 1 year ago • 2 comments

I developed a middleware to log all my requests and responses:

<?php

namespace App\Http\Integrations;

use Illuminate\Support\Facades\Log;
use Saloon\Contracts\ResponseMiddleware;
use Saloon\Http\Response;

class LoggingMiddleware implements ResponseMiddleware
{
    public function __construct(private readonly string $connector)
    {
    }

    public function __invoke(Response $response, ): void
    {
        // Log the request
        Log::info($this->connector . ' API Call', [
            'request' => [
                'method' => $response->getRequest()->getMethod()->value,
                'url' => $response->getRequest()->resolveEndpoint(),
                'headers' => $response->getRequest()->headers()->all(),
                'query' => $response->getRequest()->query()->all(),
                'body' => $response->getPendingRequest()->body()->all(),
            ],
            'response' => [
                'status' => $response->status(),
                'headers' => $response->headers()->all(),
                'body' => $response->body(),
            ],
        ]);
    }
}

Include in the construct

       $this->middleware()->onResponse(new LoggingMiddleware('Name'),order: PipeOrder::FIRST);

But if I use the Rate Limit plugin and an exception is thrown by the plugin, my middleware is not called.

IgordeOliveira avatar Jan 29 '25 00:01 IgordeOliveira

Hi @IgordeOliveira I have just release the initial version of Barstool which should solve all your problems although it will save the logs to a database.

Would be interested to hear your thoughts and to see if it works with the RateLimit plugin, I don't see why not.

Your issue is that the onResponse middleware doesn't get run when an exception is thrown. You need to use the ->onFatal() (I believe, I'm on my phone so can't check). Maybe check the implementation of Barstool if you want to carry on with your solution.

craigpotter avatar Jan 30 '25 19:01 craigpotter

@IgordeOliveira The implementation of the Rate Limit plugin involves two middleware components:

  1. The first middleware is applied to requests, checking whether the rate limit has been reached before sending the request. If the limit is exceeded, no request is sent, meaning your response middleware will not execute since there's no outgoing request.

  2. The second middleware is applied to responses, allowing it to inspect status codes and retrieve Retry-After values. This response middleware has a priority of first. Additionally, because Rate Limit is a plugin, its middleware runs before any user-added middlewares (including yours). As a result, if an exception is thrown by the Rate Limit plugin’s logic, your custom middleware will not be executed.

yankewei avatar Jun 17 '25 08:06 yankewei