写在前面
Shelf 是 Dart 生态系统中的轻量级 Web 服务器框架,专为构建 HTTP 服务器和 API 代理而设计。为什么我会使用到他,因为我接到了一个新的需求
即设备B不能直接往服务器发送请求,要通过设备A进行服务转发。因此我需要在设备A中启动一个服务来接收B的请求并转发出去。
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 设备B │ │ 设备A │ │ 服务器 │
│ (代理设备) │────▶│ (主设备) │────▶│ │
│ │ │ 代理服务器 │ │ │
└─────────────┘ │ Port: 8088 │ └─────────────┘
└─────────────┘
Shelf 核心特性
- ✅ 轻量级:最小化依赖,快速启动
- ✅ Dart 原生:与 Flutter 完美集成
- ✅ 异步友好:原生支持 async/await
- ✅ 中间件架构:可扩展的请求处理管道
- ✅ 类型安全:强类型支持,编译时检查
依赖配置
pubspec.yaml 配置
yaml
dependencies:
shelf: ^1.4.1
shelf_router: ^1.1.4
shelf_static: ^1.1.2 # 可选:静态文件服务
导入语句
dart
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_router/shelf_router.dart';
怎么使用
1. Handler(处理器)
Shelf 的核心是 Handler - 一个处理 HTTP 请求并返回响应的函数:
dart
typedef Handler = FutureOr<Response> Function(Request request);
2. Request(请求对象)
封装 HTTP 请求的所有信息:
dart
shelf.Request request = ...;
// 获取请求信息
String method = request.method; // GET, POST, etc.
Uri url = request.url; // 请求URL
Map<String, String> headers = request.headers; // 请求头
Map<String, String> params = request.params; // 路径参数
3. Response(响应对象)
创建 HTTP 响应:
dart
shelf.Response response = shelf.Response(
200, // 状态码
headers: {'Content-Type': 'application/json'},
body: '{"message": "Hello World"}',
);
在代理服务器中的应用
项目中的使用场景
比如在在我代理服务器中,Shelf 主要用于:
- HTTP 服务器:监听端口,接收代理设备请求
- 路由管理:将不同 API 路径分发到对应处理器
- 请求转发:将客户端请求转发到目标服务器
- 响应代理:将目标服务器响应返回给客户端
核心代码结构
dart
class ProxyService {
static HttpServer? _server;
/// 启动代理服务器
static Future<void> startProxy() async {
final router = Router();
// 注册 API 路由
router.all('/apis/<path|.*>', _handleApiRequest);
// 启动 HTTP 服务器
_server = await io.serve(router, '0.0.0.0', 8088);
}
/// 处理 API 请求
static Future<shelf.Response> _handleApiRequest(shelf.Request request) async {
// 1. 解析请求
final path = request.params['path'] ?? '';
final headers = Map<String, String>.from(request.headers);
// 2. 转发请求到目标服务器
final response = await http.get('target-url', headers: headers);
// 3. 返回响应
return shelf.Response(response.statusCode, body: response.body);
}
}
API 说明
服务器启动和关闭
io.serve() - 启动服务器
dart
HttpServer server = await io.serve(
handler, // 请求处理器
'0.0.0.0', // 监听地址(0.0.0.0 监听所有接口)
8088, // 监听端口
);
server.close() - 关闭服务器
dart
await server.close();
// 优雅关闭,完成当前请求后再停止
路由管理
Router 基本使用
dart
final router = Router();
// 注册路由
router.get('/users', getUsersHandler);
router.post('/users', createUserHandler);
router.get('/users/<id>', getUserByIdHandler);
路由匹配语法
dart
// 基本路径
router.get('/api/users', handler);
// 路径参数
router.get('/users/<id>', (Request request) {
String userId = request.params['id']!;
return Response.ok('User ID: $userId');
});
// 通配符匹配
router.all('/api/<path|.*>', apiHandler);
// 正则表达式(通过自定义中间件)
HTTP 方法支持
dart
router.get('/path', handler); // GET 请求
router.post('/path', handler); // POST 请求
router.put('/path', handler); // PUT 请求
router.delete('/path', handler); // DELETE 请求
router.patch('/path', handler); // PATCH 请求
router.head('/path', handler); // HEAD 请求
router.options('/path', handler); // OPTIONS 请求
router.all('/path', handler); // 匹配所有方法
请求处理
Request 对象属性
dart
Future<shelf.Response> handler(shelf.Request request) async {
// 请求方法
String method = request.method; // 'GET', 'POST', etc.
// 请求URL
Uri url = request.url; // 相对URL
String path = url.path; // 路径部分
String query = url.query; // 查询字符串
// 请求头
Map<String, String> headers = request.headers;
String? contentType = headers['content-type'];
// 路径参数(来自路由匹配)
Map<String, String> params = request.params;
String? userId = params['id'];
// 请求体
String body = await request.readAsString();
// 处理请求...
}
读取请求体
dart
// 读取为字符串
String body = await request.readAsString();
// 读取为字节
List<int> bytes = await request.read().expand((chunk) => chunk).toList();
// 读取 JSON
Map<String, dynamic> jsonData = json.decode(await request.readAsString());
响应创建
Response 静态方法
dart
// 常用响应
return shelf.Response.ok('Success'); // 200 OK
return shelf.Response.notFound('Not Found'); // 404 Not Found
return shelf.Response.forbidden('Forbidden'); // 403 Forbidden
return shelf.Response.internalServerError('Error'); // 500 Internal Server Error
// 自定义响应
return shelf.Response(
201, // 状态码
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
body: json.encode({'id': 123, 'name': 'John'}),
);
Response 构造函数参数
dart
shelf.Response(
statusCode, // HTTP 状态码 (int)
headers: {}, // 响应头 (Map<String, String>)
body: '', // 响应体 (String, List<int>, Stream, etc.)
encoding: utf8, // 文本编码 (Encoding)
context: {}, // 上下文数据 (Map<String, Object>)
);
中间件(Middleware)
内置中间件
dart
import 'package:shelf/shelf.dart' as shelf;
// 日志中间件
final handler = const shelf.Pipeline()
.addMiddleware(shelf.logRequests())
.addHandler(app);
// CORS 中间件
Middleware corsHeaders = (Handler handler) {
return (Request request) async {
final response = await handler(request);
return response.change(headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE',
'Access-Control-Allow-Headers': 'Content-Type',
});
};
};
// 自定义中间件
Middleware authentication = (Handler handler) {
return (Request request) async {
final token = request.headers['authorization'];
if (token == null) {
return shelf.Response.forbidden('No token provided');
}
// 验证 token...
return handler(request);
};
};
// 使用中间件
final app = const shelf.Pipeline()
.addMiddleware(corsHeaders)
.addMiddleware(authentication)
.addMiddleware(shelf.logRequests())
.addHandler(router);
完整示例
简单 HTTP 服务器
dart
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as io;
void main() async {
// 创建处理器
shelf.Response handler(shelf.Request request) {
return shelf.Response.ok('Hello, ${request.url.path}!');
}
// 启动服务器
final server = await io.serve(handler, 'localhost', 8080);
print('Server listening on http://localhost:8080');
}
REST API 服务器
dart
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_router/shelf_router.dart';
class ApiServer {
Router get router {
final router = Router();
router.get('/api/users', (shelf.Request request) {
return shelf.Response.ok(
json.encode([{'id': 1, 'name': 'John'}, {'id': 2, 'name': 'Jane'}]),
headers: {'Content-Type': 'application/json'},
);
});
router.post('/api/users', (shelf.Request request) async {
final body = await request.readAsString();
final user = json.decode(body);
// 保存用户...
return shelf.Response(201, body: json.encode({'id': 3, ...user}));
});
router.get('/api/users/<id>', (shelf.Request request) {
final id = request.params['id'];
return shelf.Response.ok(json.encode({'id': id, 'name': 'User $id'}));
});
return router;
}
Future<void> start() async {
final server = await io.serve(router, '0.0.0.0', 8080);
print('API Server running on http://localhost:8080');
}
}
代理服务器示例
dart
class ProxyServer {
Future<shelf.Response> proxyHandler(shelf.Request request) async {
// 构建目标URL
final targetUrl = 'https://api.example.com${request.url}';
// 转发请求
final response = await http.get(
Uri.parse(targetUrl),
headers: request.headers,
);
// 返回响应
return shelf.Response(
response.statusCode,
headers: response.headers,
body: response.body,
);
}
Future<void> start() async {
final router = Router();
router.all('/api/<path|.*>', proxyHandler);
final server = await io.serve(router, '0.0.0.0', 8088);
print('Proxy server running on port 8088');
}
}