如何在Dart服务端使用shelf获取用户IP地址?
在Shelf框架中获取客户端IP地址
问题分析
你尝试的代码返回null,通常是因为无反向代理场景下x-forwarded-for请求头不存在,且连接信息的获取或类型处理存在疏漏。以下是修正后的可行方案:
解决方案
修改路由处理函数,通过以下方式正确获取客户端IP:
import 'dart:io'; import 'package:shelf/shelf.dart'; import 'package:shelf/shelf_io.dart' as shelf_io; import 'package:shelf_router/shelf_router.dart' as shelf_router; import 'package:shelf_static/shelf_static.dart' as shelf_static; Future main(List<String> arguments) async { final cascade = Cascade().add(_staticHandler).add(_router); final server = await shelf_io.serve(logRequests().addHandler(cascade.handler), InternetAddress.anyIPv4, 8080); print('Server running on ${server.address.address}:${server.port}'); } final _staticHandler = shelf_static.createStaticHandler('public', defaultDocument: 'index.html'); final _router = shelf_router.Router() ..get('/get', (Request request) async { String? clientIp; // 1. 反向代理场景(如Nginx):优先读取X-Forwarded-For头 final forwardedFor = request.headers['x-forwarded-for']; if (forwardedFor != null && forwardedFor.isNotEmpty) { // 该头可能包含多个IP,取第一个为原始客户端IP clientIp = forwardedFor.split(',').first.trim(); } // 2. 直接连接场景:从框架注入的连接信息中获取IP else { final connectionInfo = request.context['shelf.io.connection'] as HttpConnectionInfo?; clientIp = connectionInfo?.remoteAddress.address; } return Response(HttpStatus.ok, body: 'Your IP address is: $clientIp'); }) ..post('/post', (Request request) async { String? clientIp; final forwardedFor = request.headers['x-forwarded-for']; if (forwardedFor != null && forwardedFor.isNotEmpty) { clientIp = forwardedFor.split(',').first.trim(); } else { final connectionInfo = request.context['shelf.io.connection'] as HttpConnectionInfo?; clientIp = connectionInfo?.remoteAddress.address; } return Response(HttpStatus.ok, body: 'Post request from IP: $clientIp'); }) ..all('/<ignored|.*>', (Request request) { return Response(HttpStatus.notFound); });
关键说明
- 反向代理适配:若服务部署在Nginx等反向代理后,需确保代理服务器配置了
X-Forwarded-For头,将客户端真实IP传递给Shelf服务。 - 直接连接逻辑:
request.context['shelf.io.connection']是Shelf框架自动注入的连接信息对象,包含直接连接的客户端IP,类型转换时需注意空安全判断。 - 异常规避:添加了对
x-forwarded-for非空的校验,避免空字符串分割导致的运行时异常。
内容的提问来源于stack exchange,提问作者Sittiphan Sittisak
相关产品推荐
相关产品推荐

