Flutter for OpenHarmony:shelf_proxy 构建反向代理,解决跨域与 API 转发难题(Shelf 中间件) 深度解析与鸿蒙适配指南
在进行 Web 或桌面应用开发时,我们经常遇到 CORS(跨域资源共享)问题,或者需要访问只能在内网中访问的 API。在本地启动一个反向代理(Reverse Proxy)是最常见的解决方案。是 Dart Shelf 生态中的一颗明珠,它能将发往本机的请求,无缝转发给远程服务器,并把响应原样返回给你。这类似于 Nginx 的proxy_pass,但它是用纯 Dart 写的,随开随用。: 核心处理器,
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

前言
在进行 Web 或桌面应用开发时,我们经常遇到 CORS(跨域资源共享)问题,或者需要访问只能在内网中访问的 API。在本地启动一个反向代理(Reverse Proxy)是最常见的解决方案。
shelf_proxy 是 Dart Shelf 生态中的一颗明珠,它能将发往本机的请求,无缝转发给远程服务器,并把响应原样返回给你。这类似于 Nginx 的 proxy_pass,但它是用纯 Dart 写的,随开随用。
一、概念介绍/原理解析
1.1 基础概念
- ProxyHandler: 核心处理器,接收请求,向目标 URL 发起新请求,并将结果流式传回。
- Upstream: 上游服务器(被代理的目标)。
- Rewrite: 路径重写(如
/api->/v1)。
1.2 进阶概念
它不仅支持 HTTP GET/POST,还完美支持 WebSocket 代理(用于调试即时通讯)。
二、核心 API/组件详解
2.1 依赖安装
dependencies:
shelf: ^1.4.0
shelf_proxy: ^1.0.0
2.2 基础用法
将 localhost:8080 的所有请求转发到 example.com。
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_proxy/shelf_proxy.dart';
void main() async {
// 1. 创建代理 Handler
var handler = proxyHandler('https://example.com');
// 2. 启动服务
var server = await io.serve(handler, 'localhost', 8080);
print('Proxying at http://${server.address.host}:${server.port}');
}

三、常见应用场景
3.1 场景 1:解决 Flutter Web 跨域
开发时后端 API 没有配置 CORS,浏览器直接报错。通过本地代理绕过浏览器的同源策略检查。
// 前端请求 http://localhost:8080/api/...
// 代理转发 -> https://api.backend.com/...
final proxy = proxyHandler('https://api.backend.com');
3.2 场景 2:内网 API 穿透
通过 SSH 隧道将远程端口映射到本地后,再用 shelf_proxy 进行路径调整,模拟复杂的微服务路由。
// 比如将 /service-a 转发到 localhost:3000
// 将 /service-b 转发到 localhost:4000
final cascade = Cascade()
.add(createStaticHandler('public'))
.add(proxyHandler('http://localhost:3000'));

3.3 场景 3:API Mock 与录制
在测试时,先将请求代理到真实服务器,同时记录请求/响应数据,用于生成 Mock 数据。
// 拦截并记录
final loggingProxy = (Request request) async {
print('Proxying: ${request.url}');
final response = await proxyHandler(targetUrl)(request);
print('Status: ${response.statusCode}');
return response;
};

四、OpenHarmony 平台适配
4.1 网络环境
OpenHarmony 设备通常处于复杂的网络环境中(如企业内网)。利用 shelf_proxy 可以快速搭建一个临时的调试网关,或者让多个鸿蒙设备共享同一个 PC 的网络出口。
4.2 性能
Dart 网络库基于非阻塞 I/O,shelf_proxy 的吞吐量相当可观,足以支撑一般的调试和轻量级服务需求。
五、完整示例代码
本示例展示一个带有路径重写的反向代理服务器。它将本地 /api/v1/* 的请求转发到 jsonplaceholder.typicode.com/*。
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_proxy/shelf_proxy.dart';
void main() async {
// 目标 API
const target = 'https://jsonplaceholder.typicode.com';
// 创建代理 Handler
final proxy = proxyHandler(target);
// 自定义 Handler:不仅做代理,还可以修改请求路径
final handler = (Request request) {
if (request.url.path.startsWith('api/v1/')) {
// 去掉前缀 /api/v1/
final newPath = request.url.path.replaceFirst('api/v1/', '');
// 构造新 URL
final newUrl = Uri.parse('$target/$newPath?${request.url.query}');
print('Rewriting: ${request.url} -> $newUrl');
// 注意:shelf_proxy 内部处理 URL 逻辑比较复杂,通常直接传 Uri 给 handler 即可
// 这里简化处理,直接用 proxyHandler 代理根路径,而在外层重写 request
return proxy(request.change(path: 'api/v1'));
}
return Response.notFound('Not Found');
};
// 启动服务器
final server = await io.serve(handler, 'localhost', 8080);
print('Listening on http://localhost:8080');
print('Try accessing: http://localhost:8080/api/v1/todos/1');
}

六、总结
shelf_proxy 是 Dart 全栈开发者的瑞士军刀。无论你是前端开发需要解决跨域,还是后端开发需要做简单的网关,它都能轻松胜任。
最佳实践:
- 超时控制:默认的
http.Client没有超时限制,建议传入自定义 client 以防止代理请求挂死。 - HTTPS 证书:如果上游是自签名 HTTPS,需要配置
SecurityContext信任证书。
更多推荐




所有评论(0)