route?->getPath(); if (!$route || str_contains($route, '{path:')) { return 'unknown'; } $method = $request->method() === 'HEAD' ? 'GET' : $request->method(); // Route matching has already constrained non-ID segments to registered literals. return $method . ' ' . preg_replace('#/\d+(?=/|$)#', '/{id}', $request->path()); } public static function listCost(Request $request): int { if ($request->method() !== 'GET') { return 0; } $path = preg_replace('#/\d+(?=/|$)#', '/{id}', $request->path()); if (!in_array($path, self::PAGED, true)) { return 0; } return (new Pagination($request->get()))->pageSize; } public static function ip(Request $request): string { // Resolved through the proxy allowlist so a deployment behind Nginx keeps per-caller // buckets; an untrusted peer's own header is still ignored. $ip = ClientIp::resolve($request); $packed = @inet_pton($ip); if ($packed === false) { return 'unknown'; } if (strlen($packed) === 16 && substr($packed, 0, 12) === str_repeat("\0", 10) . "\xff\xff") { $packed = substr($packed, 12); } return (string) inet_ntop($packed); } }