Flutter for OpenHarmony:shelf_proxy 构建反向代理,解决跨域与 API 转发难题(Shelf 中间件) 深度解析与鸿蒙适配指南

Flutter for OpenHarmony:shelf_proxy 构建反向代理,解决跨域与 API 转发难题(Shelf 中间件) 深度解析与鸿蒙适配指南

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net

在这里插入图片描述

前言

在进行 Web 或桌面应用开发时,我们经常遇到 CORS(跨域资源共享)问题,或者需要访问只能在内网中访问的 API。在本地启动一个反向代理(Reverse Proxy)是最常见的解决方案。

shelf_proxy 是 Dart Shelf 生态中的一颗明珠,它能将发往本机的请求,无缝转发给远程服务器,并把响应原样返回给你。这类似于 Nginx 的 proxy_pass,但它是用纯 Dart 写的,随开随用。

一、概念介绍/原理解析

1.1 基础概念

  • ProxyHandler: 核心处理器,接收请求,向目标 URL 发起新请求,并将结果流式传回。
  • Upstream: 上游服务器(被代理的目标)。
  • Rewrite: 路径重写(如 /api -> /v1)。

发起本地请求: localhost:8080/api/users

透明转发请求: https://api.example.com/v1/users

返回响应结果: JSON 数据

回传响应结果至原始发起端

客户端 (浏览器/App)

Shelf 代理中转中间件

远程后端 API 服务器

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';voidmain()async{// 1. 创建代理 Handlervar 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:4000final 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 =awaitproxyHandler(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';voidmain()async{// 目标 APIconst target ='https://jsonplaceholder.typicode.com';// 创建代理 Handlerfinal 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/','');// 构造新 URLfinal newUrl =Uri.parse('$target/$newPath?${request.url.query}');print('Rewriting: ${request.url} -> $newUrl');// 注意:shelf_proxy 内部处理 URL 逻辑比较复杂,通常直接传 Uri 给 handler 即可// 这里简化处理,直接用 proxyHandler 代理根路径,而在外层重写 requestreturnproxy(request.change(path:'api/v1'));}returnResponse.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 全栈开发者的瑞士军刀。无论你是前端开发需要解决跨域,还是后端开发需要做简单的网关,它都能轻松胜任。

最佳实践

  1. 超时控制:默认的 http.Client 没有超时限制,建议传入自定义 client 以防止代理请求挂死。
  2. HTTPS 证书:如果上游是自签名 HTTPS,需要配置 SecurityContext 信任证书。

Read more

【Linux】Linux 进程通信:System V 共享内存(最快方案)C++ 封装实战 + 通信案例,4 类经典 Bug 快速修复

【Linux】Linux 进程通信:System V 共享内存(最快方案)C++ 封装实战 + 通信案例,4 类经典 Bug 快速修复

前言:欢迎各位光临本博客,这里小编带你直接手撕**,文章并不复杂,愿诸君**耐其心性,忘却杂尘,道有所长!!!! IF’Maxue:个人主页  🔥 个人专栏: 《C语言》 《C++深度学习》 《Linux》 《数据结构》 《数学建模》 ⛺️生活是默默的坚持,毅力是永久的享受。不破不立! 文章目录 * 二、System V共享内存:最快的进程间通信 * 1. System V共享内存核心概念 * 2. System V共享内存原理 * (1)进程虚拟地址空间结构 * (2)共享内存映射过程 * (3)共享内存的管理:先描述,再组织 * 3. System V共享内存核心接口 * (1)生成唯一Key:ftok * (2)创建/获取共享内存:shmget

By Ne0inhk
【C++算法刷题营地】—— 【string类面试题】Cyber顶级骇客带你速刷 C++ string类 中的常见算法题

【C++算法刷题营地】—— 【string类面试题】Cyber顶级骇客带你速刷 C++ string类 中的常见算法题

⚡ CYBER_PROFILE ⚡ /// SYSTEM READY /// [WARNING]: DETECTING HIGH ENERGY 🌊 🌉 🌊 心手合一 · 水到渠成 >>> ACCESS TERMINAL <<<[ 🦾 作者主页 ][ 🔥 C语言核心 ][ 💾 编程百度 ][ 📡 代码仓库 ] --------------------------------------- Running Process: 100% | Latency: 0ms 索引与导读 * 一、字符串转换 * 1)字符串转换整数 * 关键点拨 * 完整代码 * 最直接的替代接口:stoi * 小试牛刀:整数转字符串 * 2)字符串相加 * 关键点拨 * 完整代码 * 3)仅仅反转字母 * 关键点拨 * 完整代码 * 4)反转字符串 * 4.

By Ne0inhk
C++高精度时间库——<chrono>

C++高精度时间库——<chrono>

在前面学习C语言我们就已经学习了C语言的时间库<time.h>。它操作简单、是全平台行为一致的时间库。但是它却存在着很多的问题——类型不安全,精度较低(通常为秒),扩展只能依赖编译器特制的宏。         而现代项目中如果要进行性能测试、时间间隔计算的话,C语言的<time.h>显然是不够的。因此在C++11中,引入了<chrono>这个时间库。接下来我们就来一次学习一下。         相关的英文文档为:Standard library header <chrono> (C++11) - cppreference.com         相关的测试代码已经上传至作者的个人gitee:楼田莉子/CPP代码学习 目录 设计哲学 库中的单位         时长单位(Duration Units)         时钟单位(

By Ne0inhk
华为OD机试双机位C卷 - Alice的安全旅行 (C++ & JAVA & Python & C语言 & JS & GO)

华为OD机试双机位C卷 - Alice的安全旅行 (C++ & JAVA & Python & C语言 & JS & GO)

Alice的安全旅行 华为OD机试双机位C卷 - 华为OD上机考试双机位C卷 200分题型 华为OD机试双机位C卷真题目录点击查看: 华为OD机试双机位C卷真题题库目录|机考题库 + 算法考点详解 题目描述 Alice计划从城市0出发最终到达城市N-1,他可以选择一条路线,但路上经过的城市总数(包括起点和终点)不能超过K个,每个城市都有一个安全度值,整个旅程的安全度被定义为路径上所有城市安全度的最小值,她的目标是让这个最小值尽可能高,请问Alice的旅程总体安全度最大能为多少? 输入描述 第一行有两个整数N和K,表示一共N个城市,以及Alice最多去K个城市(2<N<100000,1<K<100000) 接下来N行 每行包括一个整数h 表示去某个城市的安全度0=<h<=1000000000 接下来一行有一个整数M,表示城市间的M条道路,0<M<200000 接下来M行 每行有两个整数s0 s1

By Ne0inhk