Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# CHANGELOG

## [v1.1.x (Unreleased)](https://github.com/onlime/laravel-http-client-global-logger/compare/v1.1.0...main)
## [v1.1.x (Unreleased)](https://github.com/onlime/laravel-http-client-global-logger/compare/v1.1.1...main)


## [v1.1.1 (2023-11-13)](https://github.com/onlime/laravel-http-client-global-logger/compare/v1.1.0...v1.1.1)

- Feature | Handle Saloon events by @pascalbaljet in #2 – Can now also log Requests/Responses when using Saloon's `MockClient` by handling `SendingSaloonRequest` and `SentSaloonRequest` Saloon events.
- Added common OAuth2 keys `access_token,refresh_token,client_secret` to default body obfuscation configuration.

## [v1.1.0 (2023-11-09)](https://github.com/onlime/laravel-http-client-global-logger/compare/v1.0.2...v1.1.0)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ So, my recommendation: If you need global logging without any extra configuratio

- No obfuscation of query params, e.g. on a POST request to an OAuth2 token endpoint.

- Obfuscation currently only works in variant 1 or 3 (global logging).
- Obfuscation currently only works in variant 1 or 3 (global logging), and only on requests, not yet on response data.


## Testing
Expand Down
7 changes: 6 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,12 @@
"orchestra/testbench": "^8.8",
"pestphp/pest": "^2.20",
"pestphp/pest-plugin-arch": "^2.0",
"pestphp/pest-plugin-laravel": "^2.0"
"pestphp/pest-plugin-laravel": "^2.0",
"saloonphp/laravel-http-sender": "^2.0",
"saloonphp/laravel-plugin": "^3.0"
},
"suggest": {
"saloonphp/laravel-plugin": "To support logging of Saloon events (^3.0)"
},
"autoload": {
"psr-4": {
Expand Down
46 changes: 46 additions & 0 deletions src/EventHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace Onlime\LaravelHttpClientGlobalLogger;

use Exception;
use Illuminate\Http\Client\Events\RequestSending;
use Illuminate\Http\Client\Events\ResponseReceived;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Saloon\HttpSender\HttpSender;
use Saloon\Laravel\Events\SendingSaloonRequest;
use Saloon\Laravel\Events\SentSaloonRequest;

class EventHelper
{
public static function shouldBeLogged(object $event): bool
{
// Do not log Saloon requests if Saloon is configured to use Laravel's HTTP Client (HttpSender) unless the
// Saloon request is mocked (has a MockClient). Like this, we prevent duplicate logging of Saloon requests,
// as we're also listening to Laravel's HTTP Client events RequestSending and ResponseReceived.
if ($event instanceof SendingSaloonRequest || $event instanceof SentSaloonRequest) {
$saloonUsesHttpSender = config('saloon.default_sender') === HttpSender::class;
return $event->pendingRequest->hasMockClient() || ! $saloonUsesHttpSender;
}

return true;
}

public static function getPsrRequest(object $event): RequestInterface
{
return match (true) {
$event instanceof RequestSending || $event instanceof ResponseReceived => $event->request->toPsrRequest(),
$event instanceof SendingSaloonRequest || $event instanceof SentSaloonRequest => $event->pendingRequest->createPsrRequest(),
default => throw new Exception('Can not get PSR Request from Event: '.get_class($event)),
};
}

public static function getPsrResponse(object $event): ResponseInterface
{
return match (true) {
$event instanceof ResponseReceived => $event->response->toPsrResponse(),
$event instanceof SentSaloonRequest => $event->response->getPsrResponse(),
default => throw new Exception('Can not get PSR Response from Event: '.get_class($event)),
};
}
}
22 changes: 16 additions & 6 deletions src/Listeners/LogRequestSending.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,38 @@
use GuzzleHttp\MessageFormatter;
use Illuminate\Http\Client\Events\RequestSending;
use Illuminate\Support\Facades\Log;
use Onlime\LaravelHttpClientGlobalLogger\EventHelper;
use Onlime\LaravelHttpClientGlobalLogger\HttpClientLogger;
use Psr\Http\Message\RequestInterface;
use Saloon\Laravel\Events\SendingSaloonRequest;

class LogRequestSending
{
/**
* Handle the event if the middleware was not added manually.
* Handle the event if the HTTP Client global request middleware was not added manually
* with HttpClientLogger::addRequestMiddleware(). Always handle it for Saloon requests.
*/
public function handle(RequestSending $event): void
public function handle(RequestSending|SendingSaloonRequest $event): void
{
if (! HttpClientLogger::requestMiddlewareWasAdded()) {
$this->handleEvent($event);
if ($event instanceof RequestSending && HttpClientLogger::requestMiddlewareWasAdded()) {
return;
}

$this->handleEvent($event);
}

/**
* Handle the event.
*/
public function handleEvent(RequestSending $event): void
public function handleEvent(RequestSending|SendingSaloonRequest $event): void
{
if (! EventHelper::shouldBeLogged($event)) {
return;
}

$psrRequest = EventHelper::getPsrRequest($event);

$obfuscate = config('http-client-global-logger.obfuscate.enabled');
$psrRequest = $event->request->toPsrRequest();

if ($obfuscate) {
$psrRequest = $this->obfuscateHeaders($psrRequest);
Expand Down
13 changes: 9 additions & 4 deletions src/Listeners/LogResponseReceived.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,24 @@
use GuzzleHttp\MessageFormatter;
use Illuminate\Http\Client\Events\ResponseReceived;
use Illuminate\Support\Facades\Log;
use Onlime\LaravelHttpClientGlobalLogger\EventHelper;
use Saloon\Laravel\Events\SentSaloonRequest;

class LogResponseReceived
{
/**
* Handle the event.
*
* @return void
*/
public function handle(ResponseReceived $event)
public function handle(ResponseReceived|SentSaloonRequest $event): void
{
if (! EventHelper::shouldBeLogged($event)) {
return;
}

$formatter = new MessageFormatter(config('http-client-global-logger.format.response'));
Log::channel(config('http-client-global-logger.channel'))->info($formatter->format(
$event->request->toPsrRequest(), $event->response->toPsrResponse()
EventHelper::getPsrRequest($event),
EventHelper::getPsrResponse($event),
));
}
}
11 changes: 11 additions & 0 deletions src/Providers/EventServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
use Illuminate\Http\Client\Events\ResponseReceived;
use Onlime\LaravelHttpClientGlobalLogger\Listeners\LogRequestSending;
use Onlime\LaravelHttpClientGlobalLogger\Listeners\LogResponseReceived;
use Saloon\Laravel\Events\SendingSaloonRequest;
use Saloon\Laravel\Events\SentSaloonRequest;

class EventServiceProvider extends BaseEventServiceProvider
{
Expand All @@ -16,12 +18,21 @@ class EventServiceProvider extends BaseEventServiceProvider
* @var array
*/
protected $listen = [
// Laravel HTTP Client
RequestSending::class => [
LogRequestSending::class,
],
ResponseReceived::class => [
LogResponseReceived::class,
],

// Saloon
SendingSaloonRequest::class => [
LogRequestSending::class,
],
SentSaloonRequest::class => [
LogResponseReceived::class,
],
];

/**
Expand Down