Skip to content

Commit d9af2d1

Browse files
committed
first commit
0 parents  commit d9af2d1

File tree

11 files changed

+567
-0
lines changed

11 files changed

+567
-0
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/.phpunit.result.cache
2+
/vendor/
3+
/.idea
4+
/composer.lock
5+
/tests/_coverage

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# CHANGELOG
2+
3+
## [v0.9.1 (Unreleased)](https://github.com/onlime/laravel-http-client-global-logger/compare/v0.9...main)
4+
5+
## [v0.9 (2021-07-12)](https://github.com/onlime/laravel-http-client-global-logger/releases/tag/v0.9)
6+
7+
- Initial release

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2021 Philip Iezzi, Onlime GmbH - https://www.onlime.ch
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

README.md

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# Laravel HTTP Client Global Logger
2+
3+
[![Latest Version on Packagist](https://img.shields.io/packagist/v/onlime/laravel-http-client-global-logger.svg)](https://packagist.org/packages/onlime/laravel-http-client-global-logger)
4+
[![Packagist Downloads](https://img.shields.io/packagist/dt/onlime/laravel-http-client-global-logger.svg)](https://packagist.org/packages/onlime/laravel-http-client-global-logger)
5+
[![PHP from Packagist](https://img.shields.io/packagist/php-v/onlime/laravel-http-client-global-logger.svg)](https://packagist.org/packages/onlime/laravel-http-client-global-logger)
6+
[![GitHub License](https://img.shields.io/github/license/onlime/laravel-http-client-global-logger.svg)](https://github.com/onlime/laravel-http-client-global-logger/blob/main/LICENSE)
7+
8+
A super simple global logger for the [Laravel HTTP Client](https://laravel.com/docs/http-client).
9+
10+
## Installation
11+
12+
You can install the package via Composer:
13+
14+
```bash
15+
$ composer require onlime/laravel-http-client-global-logger
16+
```
17+
18+
## Configuration
19+
20+
This is a zero-configuration package. It is auto-discovered by Laravel and global logging is enabled by default. **No further configuration needed - you may skip directly to the [Usage](#usage) section below.**
21+
22+
Optionally publish the config file with:
23+
24+
```bash
25+
$ php artisan vendor:publish --provider="Onlime\LaravelHttpClientGlobalLogger\Providers\ServiceProvider"
26+
```
27+
28+
You may override its configuration in your `.env` - the following environment vars are supported:
29+
30+
- `HTTP_CLIENT_GLOBAL_LOGGER_ENABLED` (bool)
31+
- `HTTP_CLIENT_GLOBAL_LOGGER_MIXIN` (bool)
32+
- `HTTP_CLIENT_GLOBAL_LOGGER_CHANNEL` (string)
33+
- `HTTP_CLIENT_GLOBAL_LOGGER_LOGFILE` (string)
34+
- `HTTP_CLIENT_GLOBAL_LOGGER_REQUEST_FORMAT` (string)
35+
- `HTTP_CLIENT_GLOBAL_LOGGER_RESPONSE_FORMAT` (string)
36+
- `HTTP_CLIENT_GLOBAL_LOGGER_OBFUSCATE_ENABLED` (bool)
37+
- `HTTP_CLIENT_GLOBAL_LOGGER_OBFUSCATE_REPLACEMENT` (string)
38+
39+
(look into `config/http-client-global-logger.php` for further configuration and explanation)
40+
41+
## Features
42+
43+
Using the logger will log both the request and response of an external HTTP request made with the [Laravel HTTP Client](https://laravel.com/docs/http-client).
44+
45+
- Multi-line log records that contain full request/response information (including all headers and body)
46+
- Logging into separate logfile `http-client.log`. You're free to override this and use your own logging channel or just log to a different logfile.
47+
- Full support of [Guzzle MessageFormatter](https://github.com/guzzle/guzzle/blob/master/src/MessageFormatter.php) variable substitutions for highly customized log messages.
48+
- **Variant 1: Global logging** (default)
49+
- Zero-configuration: Global logging is enabled by default in this package.
50+
- Simple and performant implementation using `RequestSending` / `ResponseReceived` event listeners
51+
- Obfuscation of common credentials passed in request (e.g. `Authorization` header's Bearer token)
52+
- **Variant 2: Mixin** (`HTTP_CLIENT_GLOBAL_LOGGER_MIXIN=true`)
53+
- Enabled only on individual HTTP Client instances, using `Http::log()` - no global logging.
54+
- Log channel name can be set per HTTP Client instance by passing a name to `Http::log($name)`
55+
56+
## Usage
57+
58+
### Variant 1: Global Logging
59+
60+
**Just use Laravel HTTP Client as always - no need to configure anything!**
61+
62+
```php
63+
Http::get('https://example.com');
64+
```
65+
66+
Slightly more complex example:
67+
68+
```php
69+
$client = Http::withOptions([
70+
'base_uri' => 'https://example.com',
71+
'allow_redirects' => false,
72+
]);
73+
$response = $client->get('/user');
74+
```
75+
76+
### Variant 2: Mixin Variant
77+
78+
If you enable mixin variant, global logging will be turned off. Put this into your `.env`:
79+
80+
```ini
81+
HTTP_CLIENT_GLOBAL_LOGGER_MIXIN=true
82+
```
83+
84+
You could then turn on logging individually on each HTTP Client instance, using the `log()` method:
85+
86+
```php
87+
Http::log()->get('https://example.com');
88+
```
89+
90+
Logging with custom channel name (if not specified, defaults to current environment, such as `production` or `local`):
91+
92+
```php
93+
Http::log('my-api')->get('https://example.com');
94+
```
95+
96+
Slightly more complex example:
97+
98+
```php
99+
$client = Http::log('my-api')->withOptions([
100+
'base_uri' => 'https://example.com',
101+
'allow_redirects' => false,
102+
]);
103+
$response = $client->get('/user');
104+
```
105+
106+
## Logging example
107+
108+
By default, logs are written to a separate logfile `http-client.log`.
109+
110+
Log entry example:
111+
112+
```
113+
[2021-07-11 11:29:58] local.INFO: REQUEST: GET https://example.com/user
114+
GET /user HTTP/1.1
115+
User-Agent: GuzzleHttp/7
116+
Host: example.com
117+
Authorization: Bearer *******************
118+
[2021-07-11 11:29:58] local.INFO: RESPONSE: HTTP/1.1 200 OK
119+
HTTP/1.1 200 OK
120+
Date: Fri, 18 Jun 2021 09:29:58 GMT
121+
Server: nginx
122+
Content-Type: application/json
123+
{"username":"foo","email":"foo@example.com"}
124+
```
125+
126+
## FAQ
127+
128+
### How does this package differ from `bilfeldt/laravel-http-client-logger` ?
129+
130+
Honestly, I did not really look into [bilfeldt/laravel-http-client-logger](https://github.com/bilfeldt/laravel-http-client-logger), as my primary goal was to build a global logger for Laravel HTTP Client without any added bulk. Global logging currently (as of July 2021) is still an open issue, see [bilfeldt/laravel-http-client-logger#2 - Add global logging](https://github.com/bilfeldt/laravel-http-client-logger/issues/2).
131+
132+
Both packages provide a different feature set and have those advantages:
133+
134+
- [onlime/laravel-http-client-global-logger](https://github.com/onlime/laravel-http-client-global-logger) (this package)
135+
- global logging
136+
- auto-configured log channel `http-client` to log to a separate `http-client.log` file
137+
- Full support of [Guzzle MessageFormatter](https://github.com/guzzle/guzzle/blob/master/src/MessageFormatter.php) variable substitutions for highly customized log messages.
138+
- obfuscation of credentials in HTTP Client requests
139+
- [bilfeldt/laravel-http-client-logger](https://github.com/bilfeldt/laravel-http-client-logger)
140+
- conditional logging using `logWhen($condition)`
141+
- filtering of logs by HTTP response codes
142+
- currently still supports PHP 7.4+
143+
144+
So, my recommendation: If you need global logging without any extra configuration and without changing a line of code in your project, go for my package. If you don't want to log everything and wish to filter by HTTP response code, go for [Bilfeldt](https://github.com/bilfeldt)'s package. **But don't install both!**
145+
146+
## Caveats
147+
148+
- This package currently uses two different implementations for logging. In the preferred variant 1 (global logging), it is currently not possible to configure the [log channel name](https://laravel.com/docs/logging#configuring-the-channel-name) which defaults to current environment, such as `production` or `local`. If you with to use Laravel HTTP Client to access multiple different external APIs, it is nice to explicitely distinguish between them by different log channel names.
149+
150+
As a workaround, I have implemented another way of logging through `Http::log()` method as mixin. But of course, we should combine both variants into a single one for a cleaner codebase.
151+
152+
- Very basic obfuscation support using regex with lookbehind assertions (e.g. `/(?<=Authorization:\sBearer ).*/m`, modifying formatted log output. It's currently not possible to directly modify request headers or JSON data in request body.
153+
154+
- Obfuscation currently only works in variant 1 (global logging).
155+
156+
## Testing
157+
158+
TBD.
159+
160+
(any help appreciated!)
161+
162+
## Changes
163+
164+
All changes are listed in [CHANGELOG](CHANGELOG.md)
165+
166+
## Authors
167+
168+
Author of this shitty little package is **[Philip Iezzi (Onlime GmbH)](https://www.onlime.ch/)**.
169+
170+
## License
171+
172+
This package is licenced under the [MIT license](LICENSE) however support is more than welcome.

composer.json

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
{
2+
"name": "onlime/laravel-http-client-global-logger",
3+
"description": "A global logger for the Laravel HTTP Client",
4+
"keywords": [
5+
"onlime",
6+
"laravel-http-client-global-logger",
7+
"laravel",
8+
"http-client",
9+
"guzzle",
10+
"log",
11+
"logger",
12+
"logging",
13+
"psr3"
14+
],
15+
"homepage": "https://github.com/onlime/laravel-http-client-global-logger",
16+
"license": "MIT",
17+
"authors": [
18+
{
19+
"name": "Philip Iezzi",
20+
"email": "philip@onlime.ch",
21+
"role": "Developer"
22+
},
23+
{
24+
"name": "Onlime GmbH",
25+
"homepage": "https://www.onlime.ch/"
26+
}
27+
],
28+
"require": {
29+
"php": "^8.0",
30+
"guzzlehttp/guzzle": "^7.3",
31+
"illuminate/http": "^8.0",
32+
"illuminate/support": "^8.0",
33+
"monolog/monolog": "^2.0"
34+
},
35+
"autoload": {
36+
"psr-4": {
37+
"Onlime\\LaravelHttpClientGlobalLogger\\": "src/"
38+
}
39+
},
40+
"config": {
41+
"sort-packages": true
42+
},
43+
"extra": {
44+
"laravel": {
45+
"providers": [
46+
"Onlime\\LaravelHttpClientGlobalLogger\\Providers\\ServiceProvider"
47+
]
48+
}
49+
},
50+
"minimum-stability": "dev",
51+
"prefer-stable": true
52+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<?php
2+
3+
return [
4+
5+
/*
6+
|--------------------------------------------------------------------------
7+
| Enable logging
8+
|--------------------------------------------------------------------------
9+
|
10+
| Whether or not logging should be enabled/disabled.
11+
|
12+
*/
13+
'enabled' => env('HTTP_CLIENT_GLOBAL_LOGGER_ENABLED', true),
14+
15+
/*
16+
|--------------------------------------------------------------------------
17+
| Mixin variant
18+
|--------------------------------------------------------------------------
19+
|
20+
| Mixin variant enables Http:log($name) feature on Laravel HTTP Client instead
21+
| of globally logging everything. This will turn off global logging and only
22+
| log requests/responses that have been initiated by this method call.
23+
| The only advantage of using this variant is, that you can provide a log
24+
| channel name.
25+
|
26+
*/
27+
'mixin' => env('HTTP_CLIENT_GLOBAL_LOGGER_MIXIN', false),
28+
29+
/*
30+
|--------------------------------------------------------------------------
31+
| Log to channel
32+
|--------------------------------------------------------------------------
33+
|
34+
| Use the default log channel 'http-client' if you don't want to provide
35+
| your own. Logging to 'default' channel is not supported as this channel
36+
| needs to use monolog driver.
37+
|
38+
*/
39+
'channel' => env('HTTP_CLIENT_GLOBAL_LOGGER_CHANNEL', 'http-client'),
40+
41+
/*
42+
|--------------------------------------------------------------------------
43+
| Logfile
44+
|--------------------------------------------------------------------------
45+
|
46+
| This is only applied to default log channel 'http-client'.
47+
|
48+
*/
49+
'logfile' => env('HTTP_CLIENT_GLOBAL_LOGGER_LOGFILE', storage_path('logs/http-client.log')),
50+
51+
/*
52+
|--------------------------------------------------------------------------
53+
| Log message formats
54+
|--------------------------------------------------------------------------
55+
|
56+
| The following variable substitutions are supported:
57+
|
58+
| - {request}: Full HTTP request message
59+
| - {response}: Full HTTP response message
60+
| - {ts}: ISO 8601 date in GMT
61+
| - {date_iso_8601} ISO 8601 date in GMT
62+
| - {date_common_log} Apache common log date using the configured timezone.
63+
| - {host}: Host of the request
64+
| - {method}: Method of the request
65+
| - {uri}: URI of the request
66+
| - {version}: Protocol version
67+
| - {target}: Request target of the request (path + query + fragment)
68+
| - {hostname}: Hostname of the machine that sent the request
69+
| - {code}: Status code of the response (if available)
70+
| - {phrase}: Reason phrase of the response (if available)
71+
| - {error}: Any error messages (if available)
72+
| - {req_header_*}: Replace `*` with the lowercased name of a request header to add to the message
73+
| - {res_header_*}: Replace `*` with the lowercased name of a response header to add to the message
74+
| - {req_headers}: Request headers
75+
| - {res_headers}: Response headers
76+
| - {req_body}: Request body
77+
| - {res_body}: Response body
78+
|
79+
| (see https://github.com/guzzle/guzzle/blob/master/src/MessageFormatter.php)
80+
|
81+
*/
82+
'format' => [
83+
'request' => env('HTTP_CLIENT_GLOBAL_LOGGER_REQUEST_FORMAT',
84+
"REQUEST: {method} {uri}\r\n{req_headers}\r\n{req_body}"
85+
),
86+
'response' => env('HTTP_CLIENT_GLOBAL_LOGGER_RESPONSE_FORMAT',
87+
"RESPONSE: HTTP/{version} {code} {phrase}\r\n{res_headers}\r\n{res_body}\r\n"
88+
),
89+
],
90+
91+
/*
92+
|--------------------------------------------------------------------------
93+
| Obfuscation of credentials in logs
94+
|--------------------------------------------------------------------------
95+
|
96+
| Obfuscation only works if you have disabled 'mixin' above, which is the default.
97+
*/
98+
'obfuscate' => [
99+
'enabled' => env('HTTP_CLIENT_GLOBAL_LOGGER_OBFUSCATE_ENABLED', true),
100+
'replacement' => env('HTTP_CLIENT_GLOBAL_LOGGER_OBFUSCATE_REPLACEMENT', '**********'),
101+
'patterns' => [
102+
'/(?<="pass":").*(?=")/mU',
103+
'/(?<=Authorization:\sBearer ).*/m',
104+
],
105+
]
106+
];

0 commit comments

Comments
 (0)