| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162 |
- <?php
- declare(strict_types=1);
- namespace app\miniapi\protection;
- use Webman\Http\Request;
- use app\miniapi\http\Pagination;
- /** Only registered routes create endpoint buckets; IDs and query filters share quotas. */
- final class RequestProfile
- {
- private const PAGED = [
- '/api/mini/v1/packages',
- '/api/mini/v1/enterprises/{id}/ledger',
- '/api/mini/v1/enterprises/{id}/orders',
- '/api/mini/v1/enterprises/{id}/devices',
- '/api/mini/v1/drivers/{id}/tasks',
- '/api/mini/v1/agents/{id}/customers',
- '/api/mini/v1/agents/{id}/orders',
- ];
- public static function endpoint(Request $request): string
- {
- $route = $request->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
- {
- // Never trust caller-supplied X-Forwarded-For or X-Real-IP.
- $ip = $request->getRemoteIp();
- $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);
- }
- }
|