Skip to content

Commit 41f756f

Browse files
authored
feat: early capture request payload before transformation (#114)
1 parent 996de66 commit 41f756f

File tree

4 files changed

+78
-1
lines changed

4 files changed

+78
-1
lines changed

README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,45 @@ alongside other features like: auto-generated documentation, error tracking, ana
166166

167167
> See the [docs](https://docs.treblle.com/en/integrations/laravel) for this SDK to learn more.
168168
169+
## Capturing Original Request Payloads
170+
171+
Some applications use middleware to transform incoming request data before processing (e.g., converting legacy API formats to current formats). By default, Treblle captures the request data after all middleware has processed it, which means you'll see the transformed data rather than what the client originally sent.
172+
173+
If you need to capture the **original request payload** before any transformations, you can use the `treblle.early` middleware alongside your regular `treblle` middleware.
174+
175+
### When to use this feature
176+
177+
- Your API has middleware that modifies incoming request data
178+
- You want to see what clients actually sent vs. what your application processed
179+
- You need to debug issues related to request transformations
180+
- You want complete visibility into your API's request lifecycle
181+
182+
### How to use it
183+
184+
Add the `treblle.early` middleware **before** any middleware that transforms request data, but keep your regular `treblle` middleware in its usual position:
185+
186+
```php
187+
Route::middleware(['treblle.early', 'your-transformation-middleware', 'treblle'])->group(function () {
188+
// YOUR API ROUTES GO HERE
189+
Route::prefix('api')->group(function () {
190+
Route::post('users', [UserController::class, 'store']);
191+
Route::put('users/{id}', [UserController::class, 'update']);
192+
});
193+
});
194+
```
195+
196+
Or for individual routes:
197+
198+
```php
199+
Route::post('/api/legacy-endpoint', [LegacyController::class, 'handle'])
200+
->middleware(['treblle.early', 'legacy-transformer', 'treblle']);
201+
```
202+
203+
### Important notes
204+
205+
- If you don't use `treblle.early`, everything works exactly as before
206+
- This feature is completely optional and backward compatible
207+
169208
## Available SDKs
170209

171210
Treblle provides [open-source SDKs](https://docs.treblle.com/en/integrations) that let you seamlessly integrate Treblle with your REST-based APIs.

src/DataProviders/LaravelRequestDataProvider.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,18 @@ public function getRequest(): Request
3232
)->toArray()
3333
),
3434
query: $this->fieldMasker->mask($this->request->query->all()),
35-
body: $this->fieldMasker->mask($this->request->toArray()),
35+
body: $this->fieldMasker->mask($this->getRequestBody()),
3636
route_path: $this->request->route()?->toSymfonyRoute()->getPath(),
3737
);
3838
}
39+
40+
private function getRequestBody(): array
41+
{
42+
// Prioritizing original payload if captured by TreblleEarlyMiddleware.
43+
if ($this->request->attributes->has('treblle_original_payload')) {
44+
return $this->request->attributes->get('treblle_original_payload');
45+
}
46+
47+
return $this->request->toArray();
48+
}
3949
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Treblle\Laravel\Middlewares;
6+
7+
use Closure;
8+
use Illuminate\Http\Request;
9+
10+
final class TreblleEarlyMiddleware
11+
{
12+
public function handle(Request $request, Closure $next)
13+
{
14+
$request->attributes->set('treblle_original_payload', $request->all());
15+
16+
return $next($request);
17+
}
18+
}

src/TreblleServiceProvider.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66

77
use function config;
88
use Illuminate\Routing\Router;
9+
use Illuminate\Foundation\Http\Kernel;
910
use Illuminate\Support\ServiceProvider;
1011
use Illuminate\Contracts\Events\Dispatcher;
1112
use Illuminate\Foundation\Console\AboutCommand;
1213
use Treblle\Laravel\Middlewares\TreblleMiddleware;
14+
use Treblle\Laravel\Middlewares\TreblleEarlyMiddleware;
1315
use Illuminate\Contracts\Container\BindingResolutionException;
1416

1517
final class TreblleServiceProvider extends ServiceProvider
@@ -35,6 +37,14 @@ public function boot(): void
3537
$router->aliasMiddleware('treblle', TreblleMiddleware::class);
3638
}
3739

40+
if (! isset($router->getMiddleware()['treblle.early'])) {
41+
$router->aliasMiddleware('treblle.early', TreblleEarlyMiddleware::class);
42+
43+
/** @var Kernel $kernel */
44+
$kernel = $this->app->make(Kernel::class);
45+
$kernel->prependToMiddlewarePriority(TreblleEarlyMiddleware::class);
46+
}
47+
3848
/** @var Dispatcher $events */
3949
$events = $this->app->make(Dispatcher::class);
4050

0 commit comments

Comments
 (0)