diff --git a/代理服务器的新轮子:anyproxy.md b/代理服务器的新轮子:anyproxy.md index dd997cf..96b8ed0 100644 --- a/代理服务器的新轮子:anyproxy.md +++ b/代理服务器的新轮子:anyproxy.md @@ -1,40 +1,62 @@ 是的,我大支付宝的前端攻城师们又写了一个代理服务器,基于Node.js,取名 **anyproxy**([项目主页](https://github.com/alibaba/anyproxy))。 -![anyproxy](https://i.alipayobjects.com/i/ecmng/png/201409/3NKRCRk2Uf.png_250x.png) - - -业界的代理工具已经不少了,windows有fiddler,mac有charles,跨平台的有腾讯alloy team出品的liver pool。满足特定功能的民间产品更是层出不穷,如代理线上combo文件的[flex-combo](https://github.com/wayfind/flex-combo),clam中的[doji](https://github.com/mo-tools/doji)等等。 - -如此之多的产品,仍无法满足前端攻城师们奇葩的需求。举几个调试场景的栗子: - -* 调试线上页面,需要在页面里注入某个脚本,或是替换一些html数据。 -* 向同一个URL发送post,需要根据post body来mock数据。 -* 服务器不支持跨域头Access-Control-Allow-*,调试时却需要发送跨域请求。 -* 需要模拟个别接口超时。 -* 不改url,把请求发送到另一个地址,移动端的dns结果又有缓存,改host效率太低。 -* 替换cookie,模拟多账户/越过登录过程。 - -anyproxy的诞生,就是为了提供一个大底层,让类似的工具不再遥远,分分钟提升我们的调试效率。 - - -代理服务器的战略价值 +引子 -------------- -代理服务器是个中间人,站在了客户端和服务端中间,双方通信的每个比特,都会滴水不漏地经过它。 -从http协议的角度来看,它控制了完整的请求头、请求体、响应头、响应体,可以在客户端与服务端都无感知的情况下介入处理所有的流程,是通信过程中的战略要塞。 +业界的http代理工具已经不少了,windows有fiddler,mac有charles,跨平台的有liver pool。满足特定功能的民间产品更是层出不穷,如代理淘宝线上combo文件的[flex-combo](https://github.com/wayfind/flex-combo),clam中的[doji](https://github.com/mo-tools/doji)等等。 + +即使有如此之多的产品,我们仍感觉力不从心,因为前端攻城师们在各种网络环境中的奇葩需求太多了。举几个例子: + +* 调试线上页面,需要注入某个脚本,或是替换一些html数据。比如常用的移动端调试工具weinre就依赖这种方法 +* 不改url,把请求发送到某台指定的服务器,移动端的dns结果有缓存,改host又效率太低 +* 查看页面首次打开时的表现,需要阻止CDN提供304这样的响应 +* 服务器不支持跨域头Access-Control-Allow-*,调试时却需要发送跨域请求。本地服务器调试app中嵌入的离线页面时常面对这种需求 +* 替换cookie,快速实现多账户切换 +* 模拟各类网速环境 +* 接管某个API的响应,进行数据mock + +**既然现有产品无法覆盖如此复杂的调试需求,我们决定再做一个轮子,做一个适合前端攻城师调试环境的新工具。** -AnyProxy的开放式代理服务器设计 +代理服务器的战略意义 +-------------- +站在http协议的角度,前端攻城师们在网络通信层面的需求都可以归纳成: + +* 修改请求参数,如防止资源304 +* 修改响应头和内容,如脚本植入、数据mock、支持跨域请求 +* 调整网络传输环境,如网速模拟、指定服务器 + + +![](http://gtms02.alicdn.com/tps/i2/TB13s8SHpXXXXbZXpXX3d5m_VXX-800-377.png_400x400.jpg) + +此时,代理服务器就是不二之选。 + +代理服务器是个中间人,站在了客户端和服务端中间,双方通信的每个比特,都会滴水不漏地经过它。它控制了完整的请求头、请求体、响应头、响应体,可以在客户端与服务端都无感知的情况下介入处理所有的流程。只要代理服务器可以实现灵活配置,前端工程师们的奇葩需求就有出头之日了。 + + +这里,我们全新开发了一个代理服务器,取名**AnyProxy**,其基本特性为: + +* 基于nodeJS,降低前端工程师学习成本,更好地耦合现有开发环境 +* 实现代理服务器底层结构和基本功能,包括转发、HTTPS明文解析、数据统计 +* 提供web版界面,供mac/windows用户使用,实时观测网络请求 +* 开放接口,允许用户进行充分的自定义(后文详述) + +![UI](http://gtms01.alicdn.com/tps/i1/TB1IdgqGXXXXXa9apXXLExM2pXX-854-480.gif) + + +开放式代理服务器设计 --------------- -### 可编程的API接口(rule) +在无止境的需求面前,任何预定义的功能模板都会随着时间的流逝而落伍。想要扩大使用范围,不妨做成开放式的服务,在使用时进行二次开发。 -面对纷繁的调试需求,传统的“配置文件”遭遇了灵活性瓶颈,因此我们决定开放接口,由攻城师们自己来编写各类代理规则。 +这里,我们把http通信过程中的各个阶段进行抽离,分解成三个阶段: -类似obj-c中的delegate机制,我们把http请求的每个过程都进行分拆,用户可以根据需求对网络请求的任一环节进行干预。在这里,用户编写的规则文件被称为 **rule**。 +* 收到来自客户端请求之后,允许开发者直接从本地提供返回 +* 在转发请求到服务器前,允许开发者对发送的请求进行修改 +* 在收到服务器响应之后,允许开发者对响应内容进行修改,再返回给客户端 + +对于上述每个阶段,我们都提供了API接口,引入开发者编写自己的规则代码,实时干预通信过程,以此满足各类自定义需求。 -### 接口流程 - -具体来说,我们允许用户干预的接口: +具体地,我们提供的接口包括: * 收到用户请求之后 * **shouldUseLocalResponse** ,是否在本地直接发送响应(不再向服务器发出请求) @@ -48,58 +70,66 @@ AnyProxy的开放式代理服务器设计 * **replaceResponseHeader** 替换服务器响应的http头 * **replaceServerResDataAsync** 替换服务器响应的数据(异步接口) * **pauseBeforeSendingResponse** 在请求返回给用户前的延迟时间 - -### 清晰易懂的图解 -右侧加粗气泡里即是anyproxy的接口。 - -![](http://gtms01.alicdn.com/tps/i1/TB1YuKDGXXXXXX_XXXXrAlkZpXX-852-1080.png_640x640.jpg) - - -实践和sample + + +AnyProxy规则文件样例 --------------- +以“防止CDN返回304”这个需求为例,最直接的方案是拦截请求,在发送到CDN前删除header中的`if-modified-since`字段。在AnyProxy中,配置replaceRequestOption接口,三行代码就能实现这个自定义功能: -为了帮助你更快地编写规则(rule)文件,我们提供了些sample([点击访问](https://github.com/alibaba/anyproxy/tree/master/rule_sample)): +``` +//rule file +module.exports = { + //在向服务器发出请求前,AnyProxy会调用这个接口,可以在此时修改发送请求的参数 + replaceRequestOption : function(req,option){ var newOption = option; + delete newOption.headers['if-modified-since']; + return newOption; + } +}; +``` -* rule__blank.js - * 空白的规则文件模板,和一些注释 -* rule_adjust_response_time.js - * 把所有的响应延迟1500毫秒 -* rule_allow_CORS.js - * 为ajax请求增加跨域头 -* rule_intercept_some_https_requests.js - * 截获github.com的https请求,再在最后加点文字 -* rule_remove_cache_header.js - * 去除响应头里缓存相关的头 -* rule_replace_request_option.js - * 在请求发送到服务端前对参数做一些调整 -* rule_replace_response_data.js - * 修改响应数据 -* rule_replace_response_status_code.js - * 改变服务端响应的http状态码 -* rule_use_local_data.js - * 把响应映射到本地 +再举个例子,如果你想修改响应数据,在所有html文件最后加个"Hello World",就需要调用`replaceServerResDataAsync`接口,并结合`content-type`字段来进行修改,大约需要8行代码。 + +``` +//rule file +module.exports = { + replaceServerResDataAsync: function(req,res,serverResData,callback){ + //append "hello world" to all web pages + if(/html/i.test(res.headers['content-type'])){ + var newDataStr = serverResData.toString(); + newDataStr += "hello world!"; + callback(newDataStr); + }else{ + callback(serverResData); + } + } +}; +``` +为了帮助用户更快地编写规则(rule)文件,我们还提供了很多[清晰易懂的sample](https://github.com/alibaba/anyproxy/tree/master/rule_sample),如: -界面 +* 把所有的响应延迟1500毫秒 +* 为ajax请求增加跨域头 +* 截获github.com的https请求,再在最后加点文字 +* 去除响应头里缓存相关的头 +* 在请求发送到服务端前对参数做一些调整 +* 修改响应数据 +* 改变服务端响应的http状态码 +* 把响应映射到本地 + + +AnyProxy其他特性 -------------- -可视化查看流量的利器。界面中的数据通信用websocket完成,保证了传输的实时性。 +* 支持Https的中间人(man-in-the-middle)代理,同时提供便捷的根证书安装路径,方便移动端导入证书 +* 低网速网速模拟,协助调试2G/3G下的表现 +* 可以导出所有请求记录,供后期数据分析使用 +* 可以进行模块化调用,做二次封装,形成新产品 -![](http://gtms03.alicdn.com/tps/i3/TB1ddyqGXXXXXbXXpXXihxC1pXX-1000-549.jpg_640x640q90.jpg) -Https的中间人(man-in-the-middle)代理 ------------------ -Charles和fiddler有https的代理,可以做https的明文解码,anyProxy也做到了。 - -配合openSSL,制作一个根证书并在宿主机信任,anyproxy可以实时签发任意域名的二级证书,来协助https明文代理。 - -![](http://gtms03.alicdn.com/tps/i3/TB10.lRGXXXXXcCXXXXnLlk2VXX-962-514.png_400x400q90.jpg) - -其他特性 ------------------- -* 网速模拟,弱网络环境优化必备,你懂的! - -跃跃欲试? +文档和支持 -------------- -* 完整的文档和介绍:[https://github.com/alibaba/anyproxy](https://github.com/alibaba/anyproxy), 记得给我们加个star。 -* 有任何问题,请直接提issue,或者加入anyproxy用户旺旺群:1203077233。 \ No newline at end of file +![](http://gtms04.alicdn.com/tps/i4/TB1XfxDHpXXXXXpapXX20ySQVXX-512-512.png_200x200.jpg) + +* AnyProxy已经[开源在了Github](),并可以使用npm下载安装。 +* 完整的文档和介绍:[https://github.com/alibaba/anyproxy](https://github.com/alibaba/anyproxy), 喜欢的话可以给我们加个star。 +* 有任何问题,欢迎提issue,或是PR,或者加入anyproxy用户旺旺群答疑:1203077233。 \ No newline at end of file