From 0317df1dfe5aeb218c2af48db6898a21fc110b3c Mon Sep 17 00:00:00 2001 From: Chris Page Date: Mon, 4 Nov 2024 21:05:06 +0000 Subject: [PATCH] Added WithoutPan middleware --- README.md | 11 ++++++++ .../Middleware/InjectJavascriptLibrary.php | 9 ++++++- .../Laravel/Http/Middleware/WithoutPan.php | 17 +++++++++++++ .../InjectJavascriptLibraryTest.php | 25 +++++++++++++++++++ 4 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/Adapters/Laravel/Http/Middleware/WithoutPan.php diff --git a/README.md b/README.md index 5b3a467..f4517a6 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,17 @@ To flush your product analytics, you may use the `pan:flush` Artisan command: php artisan pan:flush ``` +## Exclude injection for certain routes + +If you want to exclude injection on certain routes of your application, you can +use the `Pan\Adapters\Laravel\Http\Middleware\WithoutPan` middleware: + +```php +Route::get('/no-pan', function () { + return view('no-pan'); +})->middleware(WithoutPan::class); +``` + ## How does it work? Via middleware, Pan injects a simple JavaScript library into your HTML pages. This library listens to events like `viewed`, `clicked`, or `hovered` and sends the data to your Laravel application. Note that this library does not collect any personal information; such as IP addresses, user agents, or any information that could be used to identify a user. diff --git a/src/Adapters/Laravel/Http/Middleware/InjectJavascriptLibrary.php b/src/Adapters/Laravel/Http/Middleware/InjectJavascriptLibrary.php index a3e8f93..393c59c 100644 --- a/src/Adapters/Laravel/Http/Middleware/InjectJavascriptLibrary.php +++ b/src/Adapters/Laravel/Http/Middleware/InjectJavascriptLibrary.php @@ -6,6 +6,7 @@ use Closure; use Illuminate\Http\Request; +use Illuminate\Routing\Route; use Illuminate\Support\Facades\File; use Pan\PanConfiguration; use Symfony\Component\HttpFoundation\Response; @@ -32,6 +33,11 @@ public function handle(Request $request, Closure $next): Response { /** @var Response $response */ $response = $next($request); + $route = $request->route(); + + if ($route instanceof Route && in_array(WithoutPan::class, $route->middleware())) { + return $response; + } if ($response->headers->get('Content-Type') === 'text/html; charset=UTF-8') { $content = (string) $response->getContent(); @@ -58,7 +64,8 @@ private function inject(Response $response): void $response->setContent( str_replace( '', - sprintf(<<<'HTML' + sprintf( + <<<'HTML' diff --git a/src/Adapters/Laravel/Http/Middleware/WithoutPan.php b/src/Adapters/Laravel/Http/Middleware/WithoutPan.php new file mode 100644 index 0000000..c978621 --- /dev/null +++ b/src/Adapters/Laravel/Http/Middleware/WithoutPan.php @@ -0,0 +1,17 @@ + <<<'HTML' @@ -24,6 +25,30 @@ ->assertSee('_TEST_CSRF_TOKEN_'); }); +it('does not inject the javascript library when the exclusion middleware is set', function (): void { + + Route::get('/', fn (): string => <<<'HTML' + + + My App + + +

Welcome to my app

+ + + HTML + )->middleware(WithoutPan::class); + + session()->put('_token', '_TEST_CSRF_TOKEN_'); + + $response = $this->get('/'); + + $response->assertOk() + ->assertDontSee('script') + ->assertDontSee('_TEST_CSRF_TOKEN_'); + +}); + it('does not inject the javascript library if the content type is not text/html', function (): void { Route::get('/', fn () => response('Hello, World!')->header('Content-Type', 'text/plain'));