Skip to content

Commit dab7e80

Browse files
committed
Fix message body obfuscation, preventing truncation
1 parent 42284ae commit dab7e80

File tree

3 files changed

+29
-13
lines changed

3 files changed

+29
-13
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# CHANGELOG
22

3-
## [v1.2.x (Unreleased)](https://github.com/onlime/laravel-http-client-global-logger/compare/v1.2.5...main)
3+
## [v1.2.x (Unreleased)](https://github.com/onlime/laravel-http-client-global-logger/compare/v1.2.6...main)
4+
5+
## [v1.2.6 (2025-06-30)](https://github.com/onlime/laravel-http-client-global-logger/compare/v1.2.5...v1.2.6)
6+
7+
- Fix message body obfuscation, improving the regexes in `obfuscateBody()` to prevent truncation on replacement.
48

59
## [v1.2.5 (2025-06-29)](https://github.com/onlime/laravel-http-client-global-logger/compare/v1.2.4...v1.2.5)
610

src/Traits/ObfuscatesBody.php

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,29 @@ protected function obfuscateBody(string $message): string
1616
{
1717
$replacement = config('http-client-global-logger.obfuscate.replacement');
1818

19-
foreach (config('http-client-global-logger.obfuscate.body_keys') as $key) {
19+
$bodyKeys = config('http-client-global-logger.obfuscate.body_keys');
20+
21+
// For each key, replace JSON-style and query param style
22+
foreach ($bodyKeys as $key) {
2023
$quoted = preg_quote($key, '/');
21-
// JSON-style: "key":"value"
24+
25+
// NOTES:
26+
// No multiline (/m) or ungreedy (/U) flags are needed; you only want to match within each line.
27+
// Each match is replaced in-place without modifying the rest of the string.
28+
29+
// 1. JSON-style: "key":"value"
2230
$message = preg_replace(
23-
'/(?<="'.$quoted.'":")[^"]*(?=")/mU',
24-
$replacement,
31+
'/("'.$quoted.'"\s*:\s*")[^"]*(")/',
32+
'$1'.$replacement.'$2',
2533
$message
2634
);
27-
// form-style: key=value (until & or end)
28-
$message = preg_replace(
29-
'/(?<=\b'. $quoted .'=)[^&]*(?=&|$)/',
30-
$replacement,
35+
36+
// 2. Form/query-style: key=value (stopping at & or end)
37+
// Using preg_replace_callback, so we don’t accidentally re-use the matched value or cause duplicates.
38+
// The pattern (\bkey=)[^&\s]* will match only the value, and not cross line breaks or ampersands.
39+
$message = preg_replace_callback(
40+
'/(\b'.$quoted.'=)[^&\s]*/',
41+
fn ($matches) => $matches[1].$replacement,
3142
$message
3243
);
3344
}

tests/HttpClientLoggerTest.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,14 @@ function setupLogger(): MockInterface
158158
$logger = setupLogger();
159159

160160
$logger->shouldReceive('info')->withArgs(function ($message) use ($expected) {
161-
expect($message)->toContain('REQUEST: POST https://example.com')
162-
->and($message)->toContain('Authorization: **********')
161+
expect($message)->toContain("REQUEST: POST https://example.com\r\n")
162+
->and($message)->toContain("Authorization: **********\r\n")
163163
->and($message)->toContain($expected);
164164
return true;
165165
})->once();
166166

167167
$logger->shouldReceive('info')->withArgs(function ($message) {
168-
expect($message)->toContain('RESPONSE: HTTP/1.1 200 OK');
168+
expect($message)->toContain("RESPONSE: HTTP/1.1 200 OK\r\n");
169169
return true;
170170
})->once();
171171

@@ -193,7 +193,8 @@ function setupLogger(): MockInterface
193193
$logger = setupLogger();
194194

195195
$logger->shouldReceive('info')->withArgs(function ($message) use ($expected) {
196-
expect($message)->toContain('REQUEST: GET '.$expected);
196+
expect($message)->toContain("REQUEST: GET $expected\r\n")
197+
->and(substr_count($message, "\r\n"))->toBeGreaterThan(1);
197198
return true;
198199
})->once();
199200

0 commit comments

Comments
 (0)