内网高德地图代理问题
内网离线可用|高德地图私有化部署两种代理方案实战对比(Node反向代理 + ServiceWorker拦截)
# 一、前言:内网地图痛点
在政务、园区、工厂、军工等严格内网隔离的项目中,前端项目无法直接访问外网高德域名:
webapi.amap.comjsapi-data1.amap.comwebst01.is.autonavi.com(卫星瓦片)
浏览器直接加载高德SDK会出现:跨域、混合内容、外网拦截、地图白屏、瓦片加载失败。
高德官方并未提供私有化离线部署包,因此行业通用解决方案只有两种:
- 后端代理:Node + Express 中转请求、批量替换域名(本人开源实现)
- 前端拦截:Service Worker 劫持浏览器请求,本地改写域名
本文结合真实踩坑经验,深度对比两套方案,附带开源代码、原理、优缺点、适用场景。
开源仓库:https://github.com/akcshen/gaode-proxy.git
技术栈:Node.js + Express + Axios、响应流批量替换、二进制透传
# 二、方案一:Node+Express 后端反向代理(生产主推)
# 2.1 方案原理
搭建一台内网 Node 代理服务,浏览器只访问内网代理地址,由服务端向外网请求高德资源,并且对返回内容做全局域名替换。
核心流程:
- 前端引入
http://内网ip:3000/amapproxy/maps加载SDK; - Node 服务请求官方高德SDK;
- 对 JS、JSON、文本类响应批量替换域名为内网代理地址;
- 对 PBF、PNG 瓦片二进制资源原样透传,不做编码转换;
- 浏览器拿到改写后的SDK,后续瓦片、接口全部走内网代理。
# 2.2 核心能力(开源项目能力)
| 能力 | 说明 |
|---|---|
| SDK入口代理 | /amapproxy/maps 代理高德 JS SDK |
| Loca可视化代理 | 支持 Loca 三维SDK转发 |
| 通用资源转发 | 自动转发各类 amap.com 子域名 |
| 卫星瓦片代理 | 适配 is.autonavi.com 卫星、路网瓦片 |
| 智能内容改写 | JS/JSON/URL 域名批量替换,二进制不处理 |
| 安全限制 | 限制合法子域名,防止开放代理滥用 |
# 2.3 关键技术难点(本人真实踩坑)
# 难点1:https 域名嵌套改写困难
高德SDK内部存在大量硬编码HTTPS域名、转义域名、模板域名:
- 明文:
https://webapi.amap.com - 转义:
https:\/\/webapi.amap.com - 模板:
{webst01,webst02}.is.autonavi.com
普通正则只能改明文,很多加密、分段、压缩后的HTTPS域名目前无法完全匹配,导致少量瓦片依然请求外网。
# 难点2:二进制资源不能乱改
瓦片图片、矢量PBF如果转成字符串替换,会直接损坏二进制编码,出现瓦片花屏、解析失败。
解决方案:区分响应类型,文本类替换、二进制类直透。
# 难点3:协议错乱(http/https混合)
内网是http,外网SDK写死https,改写不当会出现:
- 混合内容报错
- 接口400/403
- 瓦片跨域
项目提供 PUBLIC_BASE、PUBLIC_SCHEME 强制修正协议头。
# 2.4 优点 & 缺点
# ✅ 优点
- 前端零改动:代码不用改,只换SDK引入地址;
- 兼容性最强:IE、老旧浏览器全部支持;
- 统一管控:所有地图流量经过代理,方便防火墙管控;
- 支持缓存:可加内存缓存/Nginx缓存,加速瓦片加载。
# ❌ 缺点
- 存在少量深层加密HTTPS域名无法改写(目前遗留问题);
- 需要额外部署一台Node服务;
- 高并发下性能弱于Nginx。
# 三、方案二:Service Worker 前端请求拦截
# 3.1 方案原理
不搭建后端服务,纯前端技术。利用浏览器 ServiceWorker(SW) 拦截当前页面所有网络请求。
流程:
- 注册SW脚本,后台常驻;
- 监听所有
fetch请求; - 匹配高德域名,劫持请求;
- 改写请求Path、Header,转发到内网代理;
- 返回篡改后的响应给页面。
# 3.2 优势
- 无需后端服务,纯前端实现;
- 拦截粒度更细,能拦截JS内部动态生成的请求;
- 不需要大量正则替换文本,直接拦截网络层;
- 完美解决深层加密HTTPS域名无法替换的问题。
# 3.3 致命缺点(生产大坑)
- 必须HTTPS环境:ServiceWorker 不允许纯http内网使用;
- 不兼容老旧浏览器:IE彻底报废;
- 注册、更新、缓存机制诡异,经常拦截失效;
- 多标签页、刷新、离线状态容易BUG;
- 复杂SDK内部WebWorker发起的请求,SW拦截不到。
# 四、两套方案横向对比(总结干货)
| 对比项 | Node Express 代理 | Service Worker 前端拦截 |
|---|---|---|
| 部署难度 | 中等(部署Node服务) | 简单(纯前端) |
| 浏览器兼容性 | 极佳(兼容IE) | 差(必须HTTPS、现代浏览器) |
| 域名改写能力 | 大部分改写,少量加密HTTPS漏改 | 极强,网络层直接拦截 |
| 稳定性 | 高,适合长期生产 | 一般,缓存、刷新容易失效 |
| 运维成本 | 需维护Node进程 | 无需服务端 |
| 推荐场景 | 政务内网、老旧系统、生产环境 | 现代内网、仅测试、临时方案 |
# 五、目前最优落地组合方案
结合我实际开发踩坑,生产环境推荐组合使用:
- 主方案:Node.js 代理服务(稳定、兼容、简单);
- 补充方案:少量漏改的HTTPS域名,用 ServiceWorker 兜底拦截;
- 前置优化:外层套 Nginx 做负载、缓存、HTTPS证书终结。
# 六、开源项目使用教程
仓库地址:https://github.com/akcshen/gaode-proxy.git
# 6.1 快速启动
npm install
npm start
2
# 6.2 内网前端引入方式
<script src="http://127.0.0.1:3000/amapproxy/maps?v=2.0&key=你的Key"></script>
# 6.3 环境变量常用配置
PORT=3000
PUBLIC_BASE=http://192.168.x.x:3000
ACCESS_LOG=true
2
3
# 七、总结与后续优化方向
# 7.1 总结
高德内网代理没有完美方案,目前行业两种主流手段各有优劣:
- Node反向代理:稳重、工程化、适合生产,唯一缺点是少量加密HTTPS域名无法改写;
- ServiceWorker:拦截强、不用部署服务,但是浏览器限制太多、稳定性差。
# 7.2 后续优化计划
- 增强正则,补齐加密HTTPS域名改写规则;
- 增加内存缓存,提升瓦片加载速度;
- 集成SW兜底拦截,解决漏改请求;
- 支持Docker一键部署,降低内网部署成本。
# 八、开源地址
高德地图内网代理(Node.js)
GitHub:https://github.com/akcshen/gaode-proxy.git
欢迎Star、提Issue、共同完善内网地图代理方案。