LogoRevali

Client IP

Read the client IP with @Ip() or request.ip, and resolve it from trusted proxy headers

Every request exposes the client IP as request.ip. By default it is the TCP remote address. When the app runs behind a reverse proxy (load balancer, CDN, ingress), override trustedProxy on your app so the IP is read from a proxy header such as X-Forwarded-For instead.

Minimal example#

routes/controllers/whoami_controller.dart
import 'package:revali_router/revali_router.dart';

@Controller('whoami')
class WhoamiController {
  const WhoamiController();

  @Get()
  String? ip(@Ip() String? clientIp) => clientIp;
}
curl http://localhost:8080/api/whoami
# {"data":"127.0.0.1"}
WhereHow
Endpoint @Ip() String? ip , or @Ip.pipe(MyPipe) to transform it with a pipe
Lifecycle component / Request request.ip or context.request.ip

The value is null when no address can be determined.

Trusted proxy#

Override trustedProxy in your app:

routes/apps/main_app.dart
import 'package:revali_router/revali_router.dart';

@App()
final class MainApp extends AppConfig {
  const MainApp() : super(host: 'localhost', port: 8080);

  @override
  TrustedProxy get trustedProxy => const TrustedProxy(
        headers: ['X-Forwarded-For'],
      );
}
TrustedProxy optionDefaultBehavior
headers [] Header names to check, in order. The first header that yields a valid IP wins. Empty means proxy headers are ignored and the TCP address is used.
useLeftmostIp false false : take the rightmost valid IP in the comma-separated list (the one your proxy appended). true : take the leftmost.

Resolution details:

  • If a header is sent more than once, only the last line is used.
  • Ports are stripped (203.0.113.1:5000 and [2001:db8::1]:443 both work). Values that are not IPs are skipped.
  • If no configured header yields an IP, the TCP remote address is used.
X-Forwarded-For useLeftmostIp: false useLeftmostIp: true
203.0.113.1, 198.51.100.178 198.51.100.178 203.0.113.1

Common headers: X-Forwarded-For (nginx, HAProxy, most load balancers), X-Real-IP (nginx), CF-Connecting-IP (Cloudflare).

Security#

Only configure trustedProxy when all traffic reaches the app through proxies you control. Otherwise a client can send X-Forwarded-For itself and choose its own request.ip.

A proxy header is only trustworthy if your proxy overwrites it (or appends to it, with useLeftmostIp: false). If the proxy passes a header through untouched, do not list it in headers.

@PreventHeaders rejects any request that carries the named headers, including headers your own proxy adds. Use it to block forwarding headers only on apps or routes that are reached directly, without a proxy.

The same IP is used by @Throttle.