API Middleware

The Meerkat API uses one middleware group for public reads and another for moderation routes. Their defaults are in config/meerkat.php:

1'api' => [
2 'middleware' => [
3 'public' => ['throttle:60,1'],
4 'privileged' => ['throttle:30,1', 'auth', 'can:view comments'],
5 ],
6],

Public reads allow 60 requests per client each minute. Moderation routes require authentication and the view comments permission, and allow 30 requests per minute.

Laravel registers these groups as:

  • publicmeerkat-api-public
  • privilegedmeerkat-api-privileged

#Change the defaults

Publish the config, then edit config/meerkat.php:

1php artisan vendor:publish --tag=meerkat-config
1'middleware' => [
2 'public' => ['throttle:60,1'],
3 'privileged' => ['auth', 'can:view comments', 'throttle:300,1'],
4],

These values replace the defaults. Keep auth and can:view comments to protect moderation routes.

#Add middleware from a service provider

From any service provider's boot():

1use Illuminate\Support\Facades\Route;
2
3public function boot()
4{
5 Route::pushMiddlewareToGroup('meerkat-api-public', \App\Http\Middleware\RecaptchaGate::class);
6 Route::pushMiddlewareToGroup('meerkat-api-privileged', \App\Http\Middleware\AuditApiCall::class);
7}

pushMiddlewareToGroup adds your middleware after Meerkat's defaults without replacing them.

Call it from a service provider's boot() method. Route files and request hooks run too late.

#Change request limits

Change the throttle:max,minutes value for each group. Use custom middleware when individual routes need different limits.

#Use Sanctum authentication

For Sanctum authentication, replace auth in the privileged group:

1'middleware' => [
2 'public' => [],
3 'privileged' => ['auth:sanctum', 'can:view comments'],
4],

#Add logging, metrics, or CORS

Add logging, metrics, CORS, request tracking, or similar middleware in the same way:

1Route::pushMiddlewareToGroup('meerkat-api-public', LogApiRequests::class);
2Route::pushMiddlewareToGroup('meerkat-api-public', TraceApiRequest::class);

#Protect comment submissions

The POST /!/meerkat/comments submission route uses its own middleware group from meerkat.form.middleware:

1'form' => [
2 'middleware' => ['throttle:30,1'],
3],

Add middleware to the meerkat-form-submit group with:

1Route::pushMiddlewareToGroup('meerkat-form-submit', \App\Http\Middleware\TurnstileGate::class);

Submission middleware runs before Meerkat's rate limiter, spam guards, and database writes.

#Add Cloudflare Turnstile

Create app/Http/Middleware/TurnstileGate.php:

1namespace App\Http\Middleware;
2
3use Closure;
4use Illuminate\Http\Request;
5use Illuminate\Support\Facades\Http;
6
7class TurnstileGate
8{
9 public function handle(Request $request, Closure $next)
10 {
11 $token = $request->input('cf-turnstile-response');
12
13 $verified = Http::asForm()->post(
14 'https://challenges.cloudflare.com/turnstile/v0/siteverify',
15 [
16 'secret' => config('services.turnstile.secret'),
17 'response' => $token,
18 'remoteip' => $request->ip(),
19 ]
20 )->json('success', false);
21
22 if (! $verified) {
23 return back()
24 ->withInput()
25 ->withErrors(['cf-turnstile-response' => 'Captcha verification failed.'], 'meerkat');
26 }
27
28 return $next($request);
29 }
30}

Register from your AppServiceProvider::boot():

1Route::pushMiddlewareToGroup('meerkat-form-submit', \App\Http\Middleware\TurnstileGate::class);

Render the Turnstile widget inside {{ meerkat:form }}.

#Captcha addons that use Statamic events

Some captcha addons listen for Statamic form events instead of using middleware. Meerkat fires FormSubmitted with the meerkat form handle and SubmissionCreated after a successful save. Route middleware runs earlier. See Statamic form events.

Was this page helpful?