2017-12-01 21:30:49 +08:00
<!DOCTYPE HTML>
< html lang = "cn" >
< head >
< meta charset = "UTF-8" >
< meta content = "text/html; charset=utf-8" http-equiv = "Content-Type" >
< title > 简介 · AnyProxy< / title >
< meta http-equiv = "X-UA-Compatible" content = "IE=edge" / >
< meta name = "description" content = "" >
< meta name = "generator" content = "GitBook 3.2.2" >
< meta name = "author" content = "AnyProxy" >
< link rel = "stylesheet" href = "../gitbook/style.css" >
< link rel = "stylesheet" href = "../gitbook/gitbook-plugin-highlight/website.css" >
< link rel = "stylesheet" href = "../gitbook/gitbook-plugin-search/search.css" >
< link rel = "stylesheet" href = "../gitbook/gitbook-plugin-fontsettings/website.css" >
< meta name = "HandheldFriendly" content = "true" / >
< meta name = "viewport" content = "width=device-width, initial-scale=1, user-scalable=no" >
< meta name = "apple-mobile-web-app-capable" content = "yes" >
< meta name = "apple-mobile-web-app-status-bar-style" content = "black" >
< link rel = "apple-touch-icon-precomposed" sizes = "152x152" href = "../gitbook/images/apple-touch-icon-precomposed-152.png" >
< link rel = "shortcut icon" href = "../gitbook/images/favicon.ico" type = "image/x-icon" >
< link rel = "next" href = "./" / >
< link rel = "shortcut icon" href = "/assets/favicon.png" type = "image/png" >
< link rel = "stylesheet" href = "/assets/website.css" >
< script src = "/assets/main.js" > < / script >
< / head >
< body >
< div >
< / div >
< div class = "book" >
< div class = "book-summary" >
< div id = "book-search-input" role = "search" >
< input type = "text" placeholder = "Type to search" / >
< / div >
< nav role = "navigation" >
< ul class = "summary" >
< li class = "chapter active" data-level = "1.1" data-path = "./" >
< a href = "./" >
< div class = "summary-title-span 简介" >
简介
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.2" data-path = "./" >
< a href = "./#快速开始" >
< div class = "summary-title-span 快速开始" >
快速开始
< / div >
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.2.1" data-path = "./" >
< a href = "./#安装" >
< div class = "summary-title-span 安装" >
安装
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.2.2" data-path = "./" >
< a href = "./#启动" >
< div class = "summary-title-span 启动" >
启动
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.2.3" data-path = "./" >
< a href = "./#其他命令" >
< div class = "summary-title-span 其他命令" >
其他命令
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.2.4" data-path = "./" >
< a href = "./#作为npm模块使用" >
< div class = "summary-title-span 作为npm模块启动" >
作为npm模块启动
< / div >
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.3" data-path = "./" >
< a href = "./#代理https" >
< div class = "summary-title-span 代理HTTPS" >
代理HTTPS
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.4" data-path = "./" >
< a href = "./#rule模块" >
< div class = "summary-title-span rule模块" >
rule模块
< / div >
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.4.1" data-path = "./" >
< a href = "./#开发示例" >
< div class = "summary-title-span 开发示例" >
开发示例
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.4.2" data-path = "./" >
< a href = "./#处理流程" >
< div class = "summary-title-span 处理流程" >
处理流程
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.4.3" data-path = "./" >
< a href = "./#如何引用" >
< div class = "summary-title-span 如何引用" >
如何引用
< / div >
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.5" data-path = "./" >
< a href = "./#rule接口文档" >
< div class = "summary-title-span rule接口文档" >
rule接口文档
< / div >
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.5.1" data-path = "./" >
< a href = "./#summary" >
< div class = "summary-title-span rule-title" >
summary
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.5.2" data-path = "./" >
< a href = "./#beforesendrequest" >
< div class = "summary-title-span rule-title" >
beforeSendRequest
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.5.3" data-path = "./" >
< a href = "./#beforesendresponse" >
< div class = "summary-title-span rule-title" >
beforeSendResponse
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.5.4" data-path = "./" >
< a href = "./#beforedealhttpsrequest" >
< div class = "summary-title-span rule-title" >
beforeDealHttpsRequest
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.5.5" data-path = "./" >
< a href = "./#onerror" >
< div class = "summary-title-span rule-title" >
onError
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.5.6" data-path = "./" >
< a href = "./#onconnecterror" >
< div class = "summary-title-span rule-title" >
onConnectError
< / div >
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.6" data-path = "./" >
< a href = "./#rule样例" >
< div class = "summary-title-span rule样例" >
rule样例
< / div >
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.6.1" data-path = "./" >
< a href = "./#使用本地数据" >
< div class = "summary-title-span sample-title" >
使用本地数据
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.6.2" data-path = "./" >
< a href = "./#修改请求头" >
< div class = "summary-title-span sample-title" >
修改请求头
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.6.3" data-path = "./" >
< a href = "./#修改请求数据" >
< div class = "summary-title-span sample-title" >
修改请求数据
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.6.4" data-path = "./" >
< a href = "./#修改请求的目标地址" >
< div class = "summary-title-span sample-title" >
修改请求的目标地址
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.6.5" data-path = "./" >
< a href = "./#修改请求协议" >
< div class = "summary-title-span sample-title" >
修改请求协议
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.6.6" data-path = "./" >
< a href = "./#修改返回状态码" >
< div class = "summary-title-span sample-title" >
修改返回状态码
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.6.7" data-path = "./" >
< a href = "./#修改返回头" >
< div class = "summary-title-span sample-title" >
修改返回头
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.6.8" data-path = "./" >
< a href = "./#修改返回内容并延迟" >
< div class = "summary-title-span sample-title" >
修改返回内容并延迟
< / div >
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.7" data-path = "./" >
< a href = "./#证书配置" >
< div class = "summary-title-span 证书配置" >
证书配置
< / div >
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.7.1" data-path = "./" >
< a href = "./#osx系统信任ca证书" >
< div class = "summary-title-span OSX系统信任CA证书" >
OSX系统信任CA证书
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.7.2" data-path = "./" >
< a href = "./#windows系统信任ca证书" >
< div class = "summary-title-span Windows系统信任CA证书" >
Windows系统信任CA证书
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.7.3" data-path = "./" >
< a href = "./#配置osx系统代理" >
< div class = "summary-title-span 配置OSX系统代理" >
配置OSX系统代理
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.7.4" data-path = "./" >
< a href = "./#配置浏览器http代理" >
< div class = "summary-title-span 配置浏览器HTTP代理" >
配置浏览器HTTP代理
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.7.5" data-path = "./" >
< a href = "./#ios系统信任ca证书" >
< div class = "summary-title-span iOS系统信任CA证书" >
iOS系统信任CA证书
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.7.6" data-path = "./" >
< a href = "./#ios--103信任ca证书" >
< div class = "summary-title-span iOS >= 10.3信任CA证书" >
iOS >= 10.3信任CA证书
< / div >
< / a >
< / li >
< li class = "chapter " data-level = "1.7.7" data-path = "./" >
< a href = "./#配置iosandroid系统代理" >
< div class = "summary-title-span 配置iOS/Android系统代理" >
配置iOS/Android系统代理
< / div >
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.8" data-path = "./" >
< a href = "./#faq" >
< div class = "summary-title-span FAQ" >
FAQ
< / div >
< / a >
< / li >
< li class = "divider" > < / li >
< li >
< a href = "https://www.gitbook.com" target = "blank" class = "gitbook-link" >
Published with GitBook
< / a >
< / li >
< / ul >
< / nav >
< / div >
< div class = "book-body" >
< div class = "body-inner" >
< div class = "book-header" role = "navigation" >
<!-- Title -->
< h1 >
< i class = "fa fa-circle-o-notch fa-spin" > < / i >
< a href = "." > 简介< / a >
< / h1 >
< / div >
< div class = "page-wrapper" tabindex = "-1" role = "main" >
< div class = "page-inner" >
< div id = "book-search-results" >
< div class = "search-noresults" >
< section class = "normal markdown-section" >
< h1 id = "anyproxy" > AnyProxy< / h1 >
< blockquote >
< p > 本 文 档 的 适 用 范 围 是 AnyProxy 4.0, 欢 迎 提 供 反 馈 < / p >
< / blockquote >
< p > Ref: < a href = "../en" > English Doc< / a > < / p >
< p > AnyProxy是 一 个 开 放 式 的 HTTP代 理 服 务 器 。 < / p >
< p > Github主 页 : < a href = "https://github.com/alibaba/anyproxy/tree/4.x" target = "_blank" > https://github.com/alibaba/anyproxy/tree/4.x< / a > < / p >
< p > 主 要 特 性 包 括 : < / p >
< ul >
< li > 基 于 Node.js, 开 放 二 次 开 发 能 力 , 允 许 自 定 义 请 求 处 理 逻 辑 < / li >
< li > 支 持 Https的 解 析 < / li >
2017-12-01 21:58:32 +08:00
< li > 提 供 GUI界 面 , 用 以 观 察 请 求 < / li >
< / ul >
< p > 相 比 3.x版 本 , AnyProxy 4.0的 主 要 变 化 : < / p >
< ul >
< li > 规 则 文 件 ( Rule) 全 面 支 持 Promise和 Generator< / li >
2017-12-01 21:30:49 +08:00
< li > 简 化 了 规 则 文 件 内 的 接 口 < / li >
< li > Web版 界 面 重 构 < / li >
< / ul >
< p > < img src = "https://gw.alipayobjects.com/zos/rmsportal/JoxHUbVhXNedsPUUilnj.gif" width = "1275px" > < / p >
< h1 id = "快速开始" > 快 速 开 始 < / h1 >
< h2 id = "作为全局模块" > 作 为 全 局 模 块 < / h2 >
< h3 id = "安装" > 安 装 < / h3 >
< p > 对 于 Debian或 者 Ubuntu系 统 , 在 安 装 AnyProxy之 前 , 可 能 还 需 要 安 装 < code > nodejs-legacy< / code > < / p >
2017-12-01 21:58:32 +08:00
< pre > < code class = "lang-bash" > sudo apt-get install nodejs-legacy
2017-12-01 21:30:49 +08:00
< / code > < / pre >
< p > 然 后 , 安 装 AnyProxy< / p >
< pre > < code class = "lang-bash" > npm install -g anyproxy
< / code > < / pre >
< h3 id = "启动" > 启 动 < / h3 >
< ul >
< li > 命 令 行 启 动 AnyProxy, 默 认 端 口 号 8001< / li >
< / ul >
< pre > < code class = "lang-bash" > anyproxy
< / code > < / pre >
< ul >
< li > 启 动 后 将 终 端 http代 理 服 务 器 配 置 为 127.0.0.1:8001即 可 < / li >
< li > 访 问 < a href = "http://127.0.0.1:8002" target = "_blank" > http://127.0.0.1:8002< / a > , web界 面 上 能 看 到 所 有 的 请 求 信 息 < / li >
< / ul >
< h3 id = "其他命令" > 其 他 命 令 < / h3 >
< ul >
< li > 配 置 启 动 端 口 , 如 1080端 口 启 动 < / li >
< / ul >
< pre > < code class = "lang-bash" > anyproxy --port 1080
< / code > < / pre >
< h2 id = "作为npm模块使用" > 作 为 npm模 块 使 用 < / h2 >
< p > AnyProxy可 以 作 为 一 个 npm模 块 使 用 , 整 合 进 其 他 工 具 。 < / p >
< blockquote >
< p > 如 要 启 用 https解 析 , 请 在 代 理 服 务 器 启 动 前 自 行 调 用 < code > AnyProxy.utils.certMgr< / code > 相 关 方 法 生 成 证 书 , 并 引 导 用 户 信 任 安 装 。 或 引 导 用 户 使 用 < code > anyproxy-ca< / code > 方 法 。 < / p >
< / blockquote >
< ul >
< li > 引 入 < / li >
< / ul >
< pre > < code class = "lang-bash" > npm i anyproxy --save
< / code > < / pre >
< ul >
< li > 使 用 举 例 < / li >
< / ul >
< pre > < code class = "lang-js" > < span class = "hljs-keyword" > const< / span > AnyProxy = < span class = "hljs-built_in" > require< / span > (< span class = "hljs-string" > ' anyproxy' < / span > );
< span class = "hljs-keyword" > const< / span > options = {
port: < span class = "hljs-number" > 8001< / span > ,
rule: < span class = "hljs-built_in" > require< / span > (< span class = "hljs-string" > ' myRuleModule' < / span > ),
webInterface: {
enable: < span class = "hljs-literal" > true< / span > ,
webPort: < span class = "hljs-number" > 8002< / span > ,
wsPort: < span class = "hljs-number" > 8003< / span > ,
},
throttle: < span class = "hljs-number" > 10000< / span > ,
forceProxyHttps: < span class = "hljs-literal" > false< / span > ,
silent: < span class = "hljs-literal" > false< / span >
};
< span class = "hljs-keyword" > const< / span > proxyServer = < span class = "hljs-keyword" > new< / span > AnyProxy.ProxyServer(options);
proxyServer.on(< span class = "hljs-string" > ' ready' < / span > , () => { < span class = "hljs-comment" > /* */< / span > });
proxyServer.on(< span class = "hljs-string" > ' error' < / span > , (e) => { < span class = "hljs-comment" > /* */< / span > });
proxyServer.start();
< span class = "hljs-comment" > //when finished< / span >
proxyServer.close();
< / code > < / pre >
< ul >
< li > < p > Class: AnyProxy.proxyServer< / p >
< ul >
< li > < p > 创 建 代 理 服 务 器 < / p >
< pre > < code class = "lang-js" > < span class = "hljs-keyword" > const< / span > proxy = < span class = "hljs-keyword" > new< / span > AnyProxy.proxyServer(options)
< / code > < / pre >
< / li >
< li > < p > < code > options< / code > < / p >
< ul >
< li > < code > port< / code > {number} 必 选 , 代 理 服 务 器 端 口 < / li >
< li > < code > rule< / code > {object} 自 定 义 规 则 模 块 < / li >
< li > < code > throttle< / code > {number} 限 速 值 , 单 位 kb/s, 默 认 不 限 速 < / li >
< li > < code > forceProxyHttps< / code > {boolean} 是 否 强 制 拦 截 所 有 的 https, 忽 略 规 则 模 块 的 返 回 , 默 认 < code > false< / code > < / li >
< li > < code > silent< / code > {boolean} 是 否 屏 蔽 所 有 console输 出 , 默 认 < code > false< / code > < / li >
< li > < code > dangerouslyIgnoreUnauthorized< / code > {boolean} 是 否 忽 略 请 求 中 的 证 书 错 误 , 默 认 < code > false< / code > < / li >
< li > < code > webInterface< / code > {object} web版 界 面 配 置 < ul >
< li > < code > enable< / code > {boolean} 是 否 启 用 web版 界 面 , 默 认 < code > false< / code > < / li >
< li > < code > webPort< / code > {number} web版 界 面 端 口 号 , 默 认 < code > 8002< / code > < / li >
< / ul >
< / li >
< / ul >
< / li >
< li > < p > Event: < code > ready< / code > < / p >
< ul >
< li > 代 理 服 务 器 启 动 完 成 < / li >
< li > 示 例 < / li >
< / ul >
< pre > < code class = "lang-js" > proxy.on(< span class = "hljs-string" > ' ready' < / span > , < span class = "hljs-function" > < span class = "hljs-keyword" > function< / span > (< span class = "hljs-params" > < / span > ) < / span > { })
< / code > < / pre >
< / li >
< li > < p > Event: < code > error< / code > < / p >
< ul >
< li > 代 理 服 务 器 发 生 错 误 < / li >
< li > 示 例 < / li >
< / ul >
< pre > < code class = "lang-js" > proxy.on(< span class = "hljs-string" > ' error' < / span > , < span class = "hljs-function" > < span class = "hljs-keyword" > function< / span > (< span class = "hljs-params" > < / span > ) < / span > { })
< / code > < / pre >
< / li >
< li > < p > Method: < code > start< / code > < / p >
< ul >
< li > 启 动 代 理 服 务 器 < / li >
< li > 示 例 < / li >
< / ul >
< pre > < code class = "lang-js" > proxy.start();
< / code > < / pre >
< / li >
< li > < p > Method: < code > close< / code > < / p >
< ul >
< li > 关 闭 代 理 服 务 器 < / li >
< li > 示 例 < / li >
< / ul >
< pre > < code class = "lang-js" > proxy.close();
< / code > < / pre >
< / li >
< / ul >
< / li >
< li > < p > AnyProxy.utils.systemProxyMgr< / p >
< ul >
< li > 管 理 系 统 的 全 局 代 理 配 置 , 方 法 调 用 时 可 能 会 弹 出 密 码 框 < / li >
< li > 使 用 示 例 < / li >
< / ul >
< pre > < code class = "lang-js" > < span class = "hljs-comment" > // 配 置 127.0.0.1:8001为 全 局 http代 理 服 务 器 < / span >
AnyProxy.utils.systemProxyMgr.enableGlobalProxy(< span class = "hljs-string" > ' 127.0.0.1' < / span > , < span class = "hljs-string" > ' 8001' < / span > );
< span class = "hljs-comment" > // 关 闭 全 局 代 理 服 务 器 < / span >
AnyProxy.utils.systemProxyMgr.disableGlobalProxy();
< / code > < / pre >
< / li >
< li > < p > AnyProxy.utils.certMgr< / p >
< ul >
< li > 管 理 AnyProxy的 证 书 < / li >
< li > < code > AnyProxy.utils.certMgr.ifRootCAFileExists()< / code > < ul >
< li > 校 验 系 统 内 是 否 存 在 AnyProxy的 根 证 书 < / li >
< / ul >
< / li >
< li > < code > AnyProxy.utils.certMgr.generateRootCA(callback)< / code > < ul >
< li > 生 成 AnyProxy的 rootCA, 完 成 后 请 引 导 用 户 信 任 .crt文 件 < / li >
< / ul >
< / li >
< li > 样 例 < / li >
< / ul >
< pre > < code class = "lang-js" > < span class = "hljs-keyword" > const< / span > AnyProxy = < span class = "hljs-built_in" > require< / span > (< span class = "hljs-string" > ' AnyProxy' < / span > );
< span class = "hljs-keyword" > const< / span > exec = < span class = "hljs-built_in" > require< / span > (< span class = "hljs-string" > ' child_process' < / span > ).exec;
< span class = "hljs-keyword" > if< / span > (!AnyProxy.utils.certMgr.ifRootCAFileExists()) {
AnyProxy.utils.certMgr.generateRootCA((error, keyPath) => {
< span class = "hljs-comment" > // let users to trust this CA before using proxy< / span >
< span class = "hljs-keyword" > if< / span > (!error) {
< span class = "hljs-keyword" > const< / span > certDir = < span class = "hljs-built_in" > require< / span > (< span class = "hljs-string" > ' path' < / span > ).dirname(keyPath);
< span class = "hljs-built_in" > console< / span > .log(< span class = "hljs-string" > ' The cert is generated at' < / span > , certDir);
< span class = "hljs-keyword" > const< / span > isWin = < span class = "hljs-regexp" > /^win/< / span > .test(process.platform);
< span class = "hljs-keyword" > if< / span > (isWin) {
exec(< span class = "hljs-string" > ' start .' < / span > , { cwd: certDir });
} < span class = "hljs-keyword" > else< / span > {
exec(< span class = "hljs-string" > ' open .' < / span > , { cwd: certDir });
}
} < span class = "hljs-keyword" > else< / span > {
< span class = "hljs-built_in" > console< / span > .error(< span class = "hljs-string" > ' error when generating rootCA' < / span > , error);
}
});
}
< / code > < / pre >
< / li >
< / ul >
< h1 id = "代理https" > 代 理 HTTPS< / h1 >
< ul >
< li > AnyProxy默 认 不 对 https请 求 做 处 理 , 如 需 看 到 明 文 信 息 , 需 要 配 置 CA证 书 < / li >
< / ul >
< blockquote >
< p > 解 析 https请 求 的 原 理 是 中 间 人 攻 击 ( man-in-the-middle) , 用 户 必 须 信 任 AnyProxy生 成 的 CA证 书 , 才 能 进 行 后 续 流 程 < / p >
< / blockquote >
< ul >
< li > 生 成 证 书 并 解 析 所 有 https请 求 < / li >
< / ul >
< pre > < code class = "lang-bash" > anyproxy-ca < span class = "hljs-comment" > #生 成 rootCA证 书 , 生 成 后 需 要 手 动 信 任 < / span >
anyproxy --intercept < span class = "hljs-comment" > #启 动 AnyProxy, 并 解 析 所 有 https请 求 < / span >
< / code > < / pre >
< ul >
< li > < a href = "#证书配置" > 附 录 : 如 何 信 任 CA证 书 < / a > < / li >
< / ul >
< h1 id = "rule模块" > rule模 块 < / h1 >
< p > AnyProxy提 供 了 二 次 开 发 的 能 力 , 你 可 以 用 js编 写 自 己 的 规 则 模 块 ( rule) , 来 自 定 义 网 络 请 求 的 处 理 逻 辑 。 < / p >
< blockquote >
< p > 注 意 : 引 用 规 则 前 , 请 务 必 确 保 文 件 来 源 可 靠 , 以 免 发 生 安 全 问 题 < / p >
< / blockquote >
< p > 规 则 模 块 的 能 力 范 围 包 括 : < / p >
< ul >
< li > 拦 截 并 修 改 正 在 发 送 的 请 求 < ul >
< li > 可 修 改 内 容 包 括 请 求 头 ( request header), 请 求 体 ( request body) , 甚 至 是 请 求 的 目 标 地 址 等 < / li >
< / ul >
< / li >
< li > 拦 截 并 修 改 服 务 端 响 应 < ul >
< li > 可 修 改 的 内 容 包 括 http状 态 码 (status code)、 响 应 头 ( response header) 、 响 应 内 容 等 < / li >
< / ul >
< / li >
< li > 拦 截 https请 求 , 对 内 容 做 修 改 < ul >
< li > 本 质 是 中 间 人 攻 击 ( man-in-the-middle attack) , 需 要 客 户 端 提 前 信 任 AnyProxy生 成 的 CA< / li >
< / ul >
< / li >
< / ul >
< h3 id = "开发示例" > 开 发 示 例 < / h3 >
< ul >
< li > < p > 举 例 < / p >
< ul >
< li > 需 要 编 写 一 个 规 则 模 块 , 在 GET < a href = "http://httpbin.org/user-agent" target = "_blank" > http://httpbin.org/user-agent< / a > 的 返 回 值 里 加 上 测 试 信 息 , 并 延 迟 5秒 返 回 < / li >
< / ul >
< / li >
< li > < p > Step 1, 编 写 规 则 < / p >
< pre > < code class = "lang-js" > < span class = "hljs-comment" > // file: sample.js< / span >
< span class = "hljs-built_in" > module< / span > .exports = {
2017-12-01 21:58:32 +08:00
summary: < span class = "hljs-string" > ' a rule to hack response' < / span > ,
2017-12-01 21:30:49 +08:00
*beforeSendResponse(requestDetail, responseDetail) {
< span class = "hljs-keyword" > if< / span > (requestDetail.url === < span class = "hljs-string" > ' http://httpbin.org/user-agent' < / span > ) {
< span class = "hljs-keyword" > const< / span > newResponse = responseDetail.response;
2017-12-01 21:58:32 +08:00
newResponse.body += < span class = "hljs-string" > ' - AnyProxy Hacked!' < / span > ;
2017-12-01 21:30:49 +08:00
< span class = "hljs-keyword" > return< / span > < span class = "hljs-keyword" > new< / span > < span class = "hljs-built_in" > Promise< / span > ((resolve, reject) => {
setTimeout(() => { < span class = "hljs-comment" > // delay< / span >
resolve({ response: newResponse });
}, < span class = "hljs-number" > 5000< / span > );
});
}
},
};
< / code > < / pre >
< / li >
< li > < p > Step 2, 启 动 AnyProxy, 加 载 规 则 < / p >
< ul >
< li > 运 行 < code > anyproxy --rule sample.js< / code > < / li >
< / ul >
< / li >
< li > < p > Step 3, 测 试 规 则 < / p >
< ul >
< li > < p > 用 curl测 试 < / p >
< pre > < code class = "lang-bash" > curl http://httpbin.org/user-agent --proxy http://127.0.0.1:8001
< / code > < / pre >
< / li >
< li > < p > 用 浏 览 器 测 试 : 配 置 浏 览 器 http代 理 为 127.0.0.1:8001, 访 问 < a href = "http://httpbin.org/user-agent" target = "_blank" > http://httpbin.org/user-agent< / a > < / p >
< / li >
< li > < p > 经 过 代 理 服 务 器 后 , 期 望 的 返 回 如 下 < / p >
< / li >
< / ul >
< pre > < code > {
" user-agent" : " curl/7.43.0"
}
- AnyProxy Hacked!
< / code > < / pre > < / li >
< li > < p > Step 4, 查 看 请 求 信 息 < / p >
< ul >
< li > 浏 览 器 访 问 < a href = "http://127.0.0.1:8002" target = "_blank" > http://127.0.0.1:8002< / a > , 界 面 上 能 看 到 刚 才 的 请 求 信 息 < / li >
< / ul >
< / li >
< / ul >
< h3 id = "处理流程" > 处 理 流 程 < / h3 >
< ul >
< li > 处 理 流 程 图 如 下 < / li >
< / ul >
< p > < img src = "https://zos.alipayobjects.com/rmsportal/TWyNuSJtEZBdrdcOMRjE.png" width = "550" > < / p >
< ul >
< li > < p > 当 http请 求 经 过 代 理 服 务 器 时 , 具 体 处 理 过 程 是 : < / p >
< ul >
< li > 收 集 请 求 所 有 请 求 参 数 , 包 括 method, header, body等 < / li >
< li > AnyProxy调 用 规 则 模 块 < code > beforeSendRequest< / code > 方 法 , 由 模 块 做 处 理 , 返 回 新 的 请 求 参 数 , 或 返 回 响 应 内 容 < / li >
< li > 如 果 < code > beforeSendRequest< / code > 返 回 了 响 应 内 容 , 则 立 即 把 此 响 应 返 回 到 客 户 端 ( 而 不 再 发 送 到 真 正 的 服 务 端 ) , 流 程 结 束 。 < / li >
< li > 根 据 请 求 参 数 , 向 服 务 端 发 出 请 求 , 接 收 服 务 端 响 应 。 < / li >
< li > 调 用 规 则 模 块 < code > beforeSendResponse< / code > 方 法 , 由 模 块 对 响 应 内 容 进 行 处 理 < / li >
< li > 把 响 应 信 息 返 回 给 客 户 端 < / li >
< / ul >
< / li >
< li > < p > 当 代 理 服 务 器 收 到 https请 求 时 , AnyProxy可 以 替 换 证 书 , 对 请 求 做 明 文 解 析 。 < / p >
< ul >
< li > 调 用 规 则 模 块 < code > beforeDealHttpsRequest< / code > 方 法 , 如 果 返 回 < code > true< / code > , 会 明 文 解 析 这 个 请 求 , 其 他 请 求 不 处 理 < / li >
< li > 被 明 文 解 析 后 的 https请 求 , 处 理 流 程 同 http一 致 。 未 明 文 解 析 请 求 不 会 再 进 入 规 则 模 块 做 处 理 。 < / li >
< / ul >
< / li >
< / ul >
< h3 id = "如何引用" > 如 何 引 用 < / h3 >
< p > 如 下 几 种 方 案 都 可 以 用 来 引 用 规 则 模 块 : < / p >
< ul >
< li > 使 用 本 地 路 径 < pre > < code class = "lang-bash" > anyproxy --rule ./rule.js
< / code > < / pre >
< / li >
< li > < p > 使 用 在 线 地 址 < / p >
< pre > < code class = "lang-bash" > anyproxy --rule https://sample.com/rule.js
< / code > < / pre >
< / li >
< li > < p > 使 用 npm包 < / p >
< ul >
< li > AnyProxy使 用 < code > require()< / code > 加 载 本 地 规 则 , 你 可 以 在 参 数 里 传 入 一 个 本 地 的 npm包 路 径 , 或 是 某 个 全 局 安 装 的 npm包 < / li >
< / ul >
< pre > < code class = "lang-bash" > anyproxy --rule ./myRulePkg/ < span class = "hljs-comment" > #本 地 包 < / span >
npm i -g myRulePkg & & anyproxy --rule myRulePkg < span class = "hljs-comment" > #全 局 包 < / span >
< / code > < / pre >
< / li >
< / ul >
< h1 id = "rule接口文档" > rule接 口 文 档 < / h1 >
< p > 规 则 模 块 应 该 符 合 cmd规 范 , 一 个 典 型 的 规 则 模 块 代 码 结 构 如 下 。 模 块 中 所 有 方 法 都 是 可 选 的 , 只 需 实 现 业 务 感 兴 趣 的 部 分 即 可 。 < / p >
< pre > < code class = "lang-js" > < span class = "hljs-built_in" > module< / span > .exports = {
< span class = "hljs-comment" > // 模 块 介 绍 < / span >
summary: < span class = "hljs-string" > ' my customized rule for AnyProxy' < / span > ,
< span class = "hljs-comment" > // 发 送 请 求 前 拦 截 处 理 < / span >
*beforeSendRequest(requestDetail) { < span class = "hljs-comment" > /* ... */< / span > },
< span class = "hljs-comment" > // 发 送 响 应 前 处 理 < / span >
*beforeSendResponse(requestDetail, responseDetail) { < span class = "hljs-comment" > /* ... */< / span > },
< span class = "hljs-comment" > // 是 否 处 理 https请 求 < / span >
*beforeDealHttpsRequest(requestDetail) { < span class = "hljs-comment" > /* ... */< / span > },
< span class = "hljs-comment" > // 请 求 出 错 的 事 件 < / span >
*onError(requestDetail, error) { < span class = "hljs-comment" > /* ... */< / span > },
< span class = "hljs-comment" > // https连 接 服 务 器 出 错 < / span >
*onConnectError(requestDetail, error) { < span class = "hljs-comment" > /* ... */< / span > }
};
< / code > < / pre >
< blockquote >
< p > 规 则 文 件 中 , 除 了 summary, 都 是 由 < a href = "https://www.npmjs.com/package/co" target = "_blank" > co< / a > 驱 动 的 , 函 数 需 要 满 足 yieldable。 可 以 返 回 promise或 使 用 generator函 数 。 < / p >
< / blockquote >
< h3 id = "summary" > summary< / h3 >
< h4 id = "summary-string--summarystring" > summary(): string | summary:string< / h4 >
< ul >
< li > 规 则 模 块 的 介 绍 文 案 , 用 于 AnyProxy提 示 用 户 , 可 以 是 一 个 函 数 , 也 可 以 是 一 个 普 通 的 字 符 串 < / li >
< / ul >
< h3 id = "beforesendrequest" > beforeSendRequest< / h3 >
< h4 id = "beforesendrequestrequestdetail" > beforeSendRequest(requestDetail)< / h4 >
< ul >
< li > AnyProxy向 服 务 端 发 送 请 求 前 , 会 调 用 < code > beforeSendRequest< / code > , 并 带 上 参 数 < code > requestDetail< / code > < / li >
< li > < code > requestDetail< / code > < ul >
< li > < code > protocol< / code > {string} 请 求 使 用 的 协 议 , http或 者 https< / li >
< li > < code > requestOptions< / code > {object} 即 将 发 送 的 请 求 配 置 , 供 require(' http' ).request作 为 使 用 。 详 见 : < a href = "https://nodejs.org/api/http.html#http_http_request_options_callback" target = "_blank" > https://nodejs.org/api/http.html#http_http_request_options_callback< / a > < / li >
< li > < code > requestData< / code > {object} 请 求 Body< / li >
< li > < code > url< / code > {string} 请 求 url< / li >
< li > < code > _req< / code > {object} 请 求 的 原 始 request< / li >
< / ul >
< / li >
< li > < p > 举 例 : 请 求 < em > anyproxy.io< / em > 时 , < code > requestDetail< / code > 参 数 内 容 大 致 如 下 < / p >
< pre > < code class = "lang-js" > {
protocol: < span class = "hljs-string" > ' http' < / span > ,
url: < span class = "hljs-string" > ' http://anyproxy.io/' < / span > ,
requestOptions: {
hostname: < span class = "hljs-string" > ' anyproxy.io' < / span > ,
port: < span class = "hljs-number" > 80< / span > ,
path: < span class = "hljs-string" > ' /' < / span > ,
method: < span class = "hljs-string" > ' GET' < / span > ,
headers: {
Host: < span class = "hljs-string" > ' anyproxy.io' < / span > ,
< span class = "hljs-string" > ' Proxy-Connection' < / span > : < span class = "hljs-string" > ' keep-alive' < / span > ,
< span class = "hljs-string" > ' User-Agent' < / span > : < span class = "hljs-string" > ' ...' < / span >
}
},
requestData: < span class = "hljs-string" > ' ...' < / span > ,
_req: { < span class = "hljs-comment" > /* ... */< / span > }
}
< / code > < / pre >
< / li >
< li > < p > 以 下 几 种 返 回 都 是 合 法 的 < / p >
< ul >
< li > 不 做 任 何 处 理 , 返 回 null< / li >
< / ul >
< pre > < code class = "lang-js" > < span class = "hljs-keyword" > return< / span > < span class = "hljs-literal" > null< / span > ;
< / code > < / pre >
< ul >
< li > 修 改 请 求 协 议 , 如 强 制 改 用 https发 起 请 求 < / li >
< / ul >
< pre > < code class = "lang-js" > < span class = "hljs-keyword" > return< / span > {
protocol: < span class = "hljs-string" > ' https' < / span >
};
< / code > < / pre >
< ul >
< li > 修 改 请 求 参 数 < / li >
< / ul >
< pre > < code class = "lang-js" > < span class = "hljs-keyword" > var< / span > newOption = < span class = "hljs-built_in" > Object< / span > .assign({}, requestDetail.requestOptions);
newOption.path = < span class = "hljs-string" > ' /redirect/to/another/path' < / span > ;
< span class = "hljs-keyword" > return< / span > {
requestOptions: newOption
};
< / code > < / pre >
< ul >
< li > 修 改 请 求 body< / li >
< / ul >
< pre > < code class = "lang-js" > < span class = "hljs-keyword" > return< / span > {
requestData: < span class = "hljs-string" > ' my new request data' < / span >
< span class = "hljs-comment" > //这 里 也 可 以 同 时 加 上 requestOptions< / span >
};
< / code > < / pre >
< ul >
< li > 直 接 返 回 客 户 端 , 不 再 发 起 请 求 , 其 中 < code > statusCode< / code > < code > header< / code > 是 必 选 字 段 < / li >
< / ul >
< pre > < code class = "lang-js" > < span class = "hljs-keyword" > return< / span > {
response: {
statusCode: < span class = "hljs-number" > 200< / span > ,
header: { < span class = "hljs-string" > ' content-type' < / span > : < span class = "hljs-string" > ' text/html' < / span > },
body: < span class = "hljs-string" > ' this could be a < string> or < buffer> ' < / span >
}
};
< / code > < / pre >
< / li >
< / ul >
< h3 id = "beforesendresponse" > beforeSendResponse< / h3 >
< h4 id = "beforesendresponserequestdetail-responsedetail" > beforeSendResponse(requestDetail, responseDetail)< / h4 >
< ul >
< li > AnyProxy向 客 户 端 发 送 请 求 前 , 会 调 用 < code > beforeSendResponse< / code > , 并 带 上 参 数 < code > requestDetail< / code > < code > responseDetail< / code > < / li >
< li > < code > requestDetail< / code > 同 < code > beforeSendRequest< / code > 中 的 参 数 < / li >
< li > < code > responseDetail< / code > < ul >
< li > < code > response< / code > {object} 服 务 端 的 返 回 信 息 , 包 括 < code > statusCode< / code > < code > header< / code > < code > body< / code > 三 个 字 段 < / li >
< li > < code > _res< / code > {object} 原 始 的 服 务 端 返 回 对 象 < / li >
< / ul >
< / li >
< li > < p > 举 例 , 请 求 < em > anyproxy.io< / em > 时 , < code > responseDetail< / code > 参 数 内 容 大 致 如 下 < / p >
< pre > < code class = "lang-js" > {
response: {
statusCode: < span class = "hljs-number" > 200< / span > ,
header: {
< span class = "hljs-string" > ' Content-Type' < / span > : < span class = "hljs-string" > ' image/gif' < / span > ,
Connection: < span class = "hljs-string" > ' close' < / span > ,
< span class = "hljs-string" > ' Cache-Control' < / span > : < span class = "hljs-string" > ' ...' < / span >
},
body: < span class = "hljs-string" > ' ...' < / span >
},
_res: { < span class = "hljs-comment" > /* ... */< / span > }
}
< / code > < / pre >
< / li >
< li > < p > 以 下 几 种 返 回 都 是 合 法 的 < / p >
< ul >
< li > 不 做 任 何 处 理 , 返 回 null< / li >
< / ul >
< pre > < code class = "lang-js" > < span class = "hljs-keyword" > return< / span > < span class = "hljs-literal" > null< / span > ;
< / code > < / pre >
< ul >
< li > 修 改 返 回 的 状 态 码 < / li >
< / ul >
< pre > < code class = "lang-js" > < span class = "hljs-keyword" > var< / span > newResponse = < span class = "hljs-built_in" > Object< / span > .assign({}, responseDetail.response);
newResponse.statusCode = < span class = "hljs-number" > 404< / span > ;
< span class = "hljs-keyword" > return< / span > {
response: newResponse
};
< / code > < / pre >
< ul >
< li > 修 改 返 回 的 内 容 < / li >
< / ul >
< pre > < code class = "lang-js" > < span class = "hljs-keyword" > var< / span > newResponse = < span class = "hljs-built_in" > Object< / span > .assign({}, responseDetail.response);
newResponse.body += < span class = "hljs-string" > ' --from anyproxy--' < / span > ;
< span class = "hljs-keyword" > return< / span > {
response: newResponse
};
< / code > < / pre >
< / li >
< / ul >
< h3 id = "beforedealhttpsrequest" > beforeDealHttpsRequest< / h3 >
< h4 id = "beforedealhttpsrequestrequestdetail" > beforeDealHttpsRequest(requestDetail)< / h4 >
< ul >
< li > AnyProxy收 到 https请 求 时 , 会 调 用 < code > beforeDealHttpsRequest< / code > , 并 带 上 参 数 < code > requestDetail< / code > < / li >
< li > 如 果 配 置 了 全 局 解 析 https的 参 数 , 则 AnyProxy会 略 过 这 个 调 用 < / li >
< li > 只 有 返 回 < code > true< / code > 时 , AnyProxy才 会 尝 试 替 换 证 书 、 解 析 https。 否 则 只 做 数 据 流 转 发 , 无 法 看 到 明 文 数 据 。 < / li >
< li > 注 意 : https over http的 代 理 模 式 中 , 这 里 的 request是 CONNECT请 求 < / li >
< li > < code > requestDetail< / code > < ul >
< li > < code > host< / code > {string} 请 求 目 标 的 Host, 受 制 于 协 议 , 这 里 无 法 获 取 完 整 url< / li >
< li > < code > _req< / code > {object} 请 求 的 原 始 request< / li >
< / ul >
< / li >
< li > 返 回 值 < ul >
< li > < code > true< / code > 或 者 < code > false< / code > , 表 示 是 否 需 要 AnyProxy替 换 证 书 并 解 析 https< / li >
< / ul >
< / li >
< / ul >
< h3 id = "onerror" > onError< / h3 >
< h4 id = "onerrorrequestdetail-error" > onError(requestDetail, error)< / h4 >
< ul >
< li > 在 请 求 处 理 过 程 中 发 生 错 误 时 , AnyProxy会 调 用 < code > onError< / code > 方 法 , 并 提 供 对 应 的 错 误 信 息 < / li >
< li > 多 数 场 景 下 , 错 误 会 在 请 求 目 标 服 务 器 的 时 候 发 生 , 比 如 DNS解 析 失 败 、 请 求 超 时 等 < / li >
< li > < code > requestDetail< / code > 同 < code > beforeSendRequest< / code > 中 的 参 数 < / li >
< li > < p > 以 下 几 种 返 回 都 是 合 法 的 < / p >
< ul >
< li > 不 做 任 何 处 理 。 此 时 AnyProxy会 返 回 一 个 默 认 的 错 误 页 。 < / li >
< / ul >
< pre > < code class = "lang-js" > < span class = "hljs-keyword" > return< / span > < span class = "hljs-literal" > null< / span > ;
< / code > < / pre >
< ul >
< li > 返 回 自 定 义 错 误 页 < / li >
< / ul >
< pre > < code class = "lang-js" > < span class = "hljs-keyword" > return< / span > {
response: {
statusCode: < span class = "hljs-number" > 200< / span > ,
header: { < span class = "hljs-string" > ' content-type' < / span > : < span class = "hljs-string" > ' text/html' < / span > },
body: < span class = "hljs-string" > ' this could be a < string> or < buffer> ' < / span >
}
};
< / code > < / pre >
< / li >
< / ul >
< h3 id = "onconnecterror" > onConnectError< / h3 >
< h4 id = "onconnecterrorrequestdetail-error" > onConnectError(requestDetail, error)< / h4 >
< ul >
< li > AnyProxy在 与 目 标 HTTPS服 务 器 建 立 连 接 的 过 程 中 , 如 果 发 生 错 误 , AnyProxy会 调 用 这 个 方 法 < / li >
< li > < code > requestDetail< / code > 同 < code > beforeDealHttpsRequest< / code > 中 的 参 数 < / li >
< li > 此 处 无 法 控 制 向 客 户 端 的 返 回 信 息 , 无 需 返 回 值 。 < / li >
< / ul >
< h1 id = "rule样例" > rule样 例 < / h1 >
< ul >
< li > 这 里 提 供 一 些 样 例 , 来 讲 解 规 则 模 块 的 常 见 用 法 < / li >
< li > 你 可 以 通 过 < code > anyproxy --rule http://....js< / code > 来 加 载 模 块 并 体 验 < / li >
< li > 用 curl发 请 求 测 试 的 方 法 如 下 < ul >
< li > 直 接 请 求 服 务 器 : < code > curl http://httpbin.org/< / code > < / li >
< li > 通 过 代 理 服 务 器 请 求 : < code > curl http://httpbin.org/ --proxy http://127.0.0.1:8001< / code > < / li >
< / ul >
< / li >
< / ul >
< h3 id = "使用本地数据" > 使 用 本 地 数 据 < / h3 >
< ul >
< li > 拦 截 发 送 到 < a href = "http://httpbin.org" target = "_blank" > http://httpbin.org< / a > 的 请 求 , 使 用 本 地 数 据 代 替 服 务 端 返 回 < / li >
< / ul >
< pre > < code class = "lang-bash" > anyproxy --rule rule_sample/sample_use_< span class = "hljs-built_in" > local< / span > _response.js
< / code > < / pre >
< pre > < code class = "lang-js" > < span class = "hljs-comment" > /*
sample:
intercept all requests toward httpbin.org, use a local response
test:
curl http://httpbin.org/user-agent --proxy http://127.0.0.1:8001
*/< / span >
< span class = "hljs-built_in" > module< / span > .exports = {
*beforeSendRequest(requestDetail) {
< span class = "hljs-keyword" > const< / span > localResponse = {
statusCode: < span class = "hljs-number" > 200< / span > ,
header: { < span class = "hljs-string" > ' Content-Type' < / span > : < span class = "hljs-string" > ' application/json' < / span > },
body: < span class = "hljs-string" > ' {" hello" : " this is local response" }' < / span >
};
< span class = "hljs-keyword" > if< / span > (requestDetail.url.indexOf(< span class = "hljs-string" > ' http://httpbin.org' < / span > ) === < span class = "hljs-number" > 0< / span > ) {
< span class = "hljs-keyword" > return< / span > {
response: localResponse
};
}
},
};
< / code > < / pre >
< h3 id = "修改请求头" > 修 改 请 求 头 < / h3 >
< ul >
< li > 修 改 发 送 到 httpbin.org 的 user-agent< / li >
< / ul >
< pre > < code class = "lang-bash" > anyproxy --rule rule_sample/sample_modify_request_header.js
< / code > < / pre >
< pre > < code class = "lang-js" > < span class = "hljs-comment" > /*
sample:
modify the user-agent in requests toward httpbin.org
test:
curl http://httpbin.org/user-agent --proxy http://127.0.0.1:8001
*/< / span >
< span class = "hljs-built_in" > module< / span > .exports = {
*beforeSendRequest(requestDetail) {
< span class = "hljs-keyword" > if< / span > (requestDetail.url.indexOf(< span class = "hljs-string" > ' http://httpbin.org' < / span > ) === < span class = "hljs-number" > 0< / span > ) {
< span class = "hljs-keyword" > const< / span > newRequestOptions = requestDetail.requestOptions;
newRequestOptions.headers[< span class = "hljs-string" > ' User-Agent' < / span > ] = < span class = "hljs-string" > ' AnyProxy/0.0.0' < / span > ;
< span class = "hljs-keyword" > return< / span > {
requestOptions: newRequestOptions
};
}
},
};
< / code > < / pre >
< h3 id = "修改请求数据" > 修 改 请 求 数 据 < / h3 >
< ul >
< li > 修 改 发 送 到 < a href = "http://httpbin.org/post" target = "_blank" > http://httpbin.org/post< / a > 的 post数 据 < / li >
< / ul >
< pre > < code class = "lang-bash" > anyproxy --rule rule_sample/sample_modify_request_data.js
< / code > < / pre >
< pre > < code class = "lang-js" > < span class = "hljs-comment" > /*
sample:
modify the post data towards http://httpbin.org/post
test:
curl -H " Content-Type: text/plain" -X POST -d ' original post data' http://httpbin.org/post --proxy http://127.0.0.1:8001
expected response:
{ " data" : " i-am-anyproxy-modified-post-data" }
*/< / span >
< span class = "hljs-built_in" > module< / span > .exports = {
summary: < span class = "hljs-string" > ' Rule to modify request data' < / span > ,
*beforeSendRequest(requestDetail) {
< span class = "hljs-keyword" > if< / span > (requestDetail.url.indexOf(< span class = "hljs-string" > ' http://httpbin.org/post' < / span > ) === < span class = "hljs-number" > 0< / span > ) {
< span class = "hljs-keyword" > return< / span > {
requestData: < span class = "hljs-string" > ' i-am-anyproxy-modified-post-data' < / span >
};
}
},
};
< / code > < / pre >
< h3 id = "修改请求的目标地址" > 修 改 请 求 的 目 标 地 址 < / h3 >
< ul >
< li > 把 所 有 发 送 到 < a href = "http://httpbin.org/" target = "_blank" > http://httpbin.org/< / a > 的 请 求 全 部 改 到 < a href = "http://httpbin.org/user-agent" target = "_blank" > http://httpbin.org/user-agent< / a > < / li >
< / ul >
< pre > < code class = "lang-bash" > anyproxy --rule rule_sample/sample_modify_request_path.js
< / code > < / pre >
< pre > < code class = "lang-js" > < span class = "hljs-comment" > /*
sample:
redirect all https://httpbin.org/user-agent requests to http://localhost:8008/index.html
test:
curl https://httpbin.org/user-agent --proxy http://127.0.0.1:8001
expected response:
' hello world' from 127.0.0.1:8001/index.html
*/< / span >
< span class = "hljs-built_in" > module< / span > .exports = {
*beforeSendRequest(requestDetail) {
< span class = "hljs-keyword" > if< / span > (requestDetail.url.indexOf(< span class = "hljs-string" > ' https://httpbin.org/user-agent' < / span > ) === < span class = "hljs-number" > 0< / span > ) {
< span class = "hljs-keyword" > const< / span > newRequestOptions = requestDetail.requestOptions;
requestDetail.protocol = < span class = "hljs-string" > ' http' < / span > ;
newRequestOptions.hostname = < span class = "hljs-string" > ' 127.0.0.1' < / span >
newRequestOptions.port = < span class = "hljs-string" > ' 8008' < / span > ;
newRequestOptions.path = < span class = "hljs-string" > ' /index.html' < / span > ;
newRequestOptions.method = < span class = "hljs-string" > ' GET' < / span > ;
< span class = "hljs-keyword" > return< / span > requestDetail;
}
},
*beforeDealHttpsRequest(requestDetail) {
< span class = "hljs-keyword" > return< / span > < span class = "hljs-literal" > true< / span > ;
}
};
< / code > < / pre >
< h3 id = "修改请求协议" > 修 改 请 求 协 议 < / h3 >
< ul >
< li > 把 用 http协 议 请 求 的 < a href = "http://httpbin.org" target = "_blank" > http://httpbin.org< / a > 改 成 https并 发 送 < / li >
< / ul >
< pre > < code class = "lang-bash" > anyproxy --rule rule_sample/sample_modify_request_protocol.js
< / code > < / pre >
< pre > < code class = "lang-js" > < span class = "hljs-comment" > /*
sample:
redirect all http requests of httpbin.org to https
test:
curl ' http://httpbin.org/get?show_env=1' --proxy http://127.0.0.1:8001
expected response:
{ " X-Forwarded-Protocol" : " https" }
*/< / span >
< span class = "hljs-built_in" > module< / span > .exports = {
*beforeSendRequest(requestDetail) {
< span class = "hljs-keyword" > if< / span > (requestDetail.url.indexOf(< span class = "hljs-string" > ' http://httpbin.org' < / span > ) === < span class = "hljs-number" > 0< / span > ) {
< span class = "hljs-keyword" > const< / span > newOption = requestDetail.requestOptions;
newOption.port = < span class = "hljs-number" > 443< / span > ;
< span class = "hljs-keyword" > return< / span > {
protocol: < span class = "hljs-string" > ' https' < / span > ,
requestOptions: newOption
};
}
}
};
< / code > < / pre >
< h3 id = "修改返回状态码" > 修 改 返 回 状 态 码 < / h3 >
< ul >
< li > 把 所 有 < a href = "http://httpbin.org" target = "_blank" > http://httpbin.org< / a > 的 返 回 状 态 码 都 改 成 404< / li >
< / ul >
< pre > < code class = "lang-bash" > anyproxy --rule rule_sample/sample_modify_response_statuscode.js
< / code > < / pre >
< pre > < code class = "lang-js" > < span class = "hljs-comment" > /*
sample:
modify all status code of http://httpbin.org/ to 404
test:
curl -I ' http://httpbin.org/user-agent' --proxy http://127.0.0.1:8001
expected response:
HTTP/1.1 404 Not Found
*/< / span >
< span class = "hljs-built_in" > module< / span > .exports = {
*beforeSendResponse(requestDetail, responseDetail) {
< span class = "hljs-keyword" > if< / span > (requestDetail.url.indexOf(< span class = "hljs-string" > ' http://httpbin.org' < / span > ) === < span class = "hljs-number" > 0< / span > ) {
< span class = "hljs-keyword" > const< / span > newResponse = responseDetail.response;
newResponse.statusCode = < span class = "hljs-number" > 404< / span > ;
< span class = "hljs-keyword" > return< / span > {
response: newResponse
};
}
}
};
< / code > < / pre >
< h3 id = "修改返回头" > 修 改 返 回 头 < / h3 >
< ul >
< li > 在 < a href = "http://httpbin.org/user-agent" target = "_blank" > http://httpbin.org/user-agent< / a > 的 返 回 头 里 加 上 X-Proxy-By:AnyProxy< / li >
< / ul >
< pre > < code class = "lang-bash" > anyproxy --rule rule_sample/sample_modify_response_header.js
< / code > < / pre >
< pre > < code class = "lang-js" > < span class = "hljs-comment" > /*
sample:
modify response header of http://httpbin.org/user-agent
test:
curl -I ' http://httpbin.org/user-agent' --proxy http://127.0.0.1:8001
expected response:
X-Proxy-By: AnyProxy
*/< / span >
< span class = "hljs-built_in" > module< / span > .exports = {
*beforeSendResponse(requestDetail, responseDetail) {
< span class = "hljs-keyword" > if< / span > (requestDetail.url.indexOf(< span class = "hljs-string" > ' http://httpbin.org/user-agent' < / span > ) === < span class = "hljs-number" > 0< / span > ) {
< span class = "hljs-keyword" > const< / span > newResponse = responseDetail.response;
newResponse.header[< span class = "hljs-string" > ' X-Proxy-By' < / span > ] = < span class = "hljs-string" > ' AnyProxy' < / span > ;
< span class = "hljs-keyword" > return< / span > {
response: newResponse
};
}
}
};
< / code > < / pre >
< h3 id = "修改返回内容并延迟" > 修 改 返 回 内 容 并 延 迟 < / h3 >
< ul >
< li > 在 < a href = "http://httpbin.org/user-agent" target = "_blank" > http://httpbin.org/user-agent< / a > 的 返 回 最 后 追 加 AnyProxy的 签 名 , 并 延 迟 5秒 < / li >
< / ul >
< pre > < code class = "lang-bash" > anyproxy --rule rule_sample/sample_modify_response_data.js
< / code > < / pre >
< pre > < code class = "lang-js" > < span class = "hljs-comment" > /*
sample:
modify response data of http://httpbin.org/user-agent
test:
curl ' http://httpbin.org/user-agent' --proxy http://127.0.0.1:8001
expected response:
{ " user-agent" : " curl/7.43.0" } -- AnyProxy Hacked! --
*/< / span >
< span class = "hljs-built_in" > module< / span > .exports = {
*beforeSendResponse(requestDetail, responseDetail) {
< span class = "hljs-keyword" > if< / span > (requestDetail.url === < span class = "hljs-string" > ' http://httpbin.org/user-agent' < / span > ) {
< span class = "hljs-keyword" > const< / span > newResponse = responseDetail.response;
newResponse.body += < span class = "hljs-string" > ' -- AnyProxy Hacked! --' < / span > ;
< span class = "hljs-keyword" > return< / span > < span class = "hljs-keyword" > new< / span > < span class = "hljs-built_in" > Promise< / span > ((resolve, reject) => {
setTimeout(() => { < span class = "hljs-comment" > // delay the response for 5s< / span >
resolve({ response: newResponse });
}, < span class = "hljs-number" > 5000< / span > );
});
}
},
};
< / code > < / pre >
< h1 id = "证书配置" > 证 书 配 置 < / h1 >
< h3 id = "osx系统信任ca证书" > OSX系 统 信 任 CA证 书 < / h3 >
< ul >
< li > 类 似 这 种 报 错 都 是 因 为 系 统 没 有 信 任 AnyProxy生 成 的 CA所 造 成 的 < / li >
< / ul >
< p > < img src = "https://zos.alipayobjects.com/rmsportal/CBkLGYgvoHAYwNVAYkpk.png" width = "450" > < / p >
< blockquote >
< p > 警 告 : CA证 书 和 系 统 安 全 息 息 相 关 , 建 议 亲 自 生 成 , 并 妥 善 保 管 < / p >
< / blockquote >
< p > 安 装 CA: < / p >
< ul >
< li > < p > 双 击 打 开 < em > rootCA.crt< / em > < / p >
< / li >
< li > < p > 确 认 将 证 书 添 加 到 login或 system< / p >
< / li >
< / ul >
< p > < img src = "https://zos.alipayobjects.com/rmsportal/bCwNUFFpvsmVuljQKrIk.png" width = "350" > < / p >
< ul >
< li > 找 到 刚 刚 导 入 的 AnyProxy证 书 , 配 置 为 信 任 ( Always Trust) < / li >
< / ul >
< p > < img src = "https://zos.alipayobjects.com/rmsportal/HOmEElNGdoZEWFMLsTNT.png" width = "700" > < / p >
< h3 id = "windows系统信任ca证书" > Windows系 统 信 任 CA证 书 < / h3 >
< p > < img src = "https://t.alipayobjects.com/tfscom/T1D3hfXeFtXXXXXXXX.jpg" width = "700" > < / p >
< h3 id = "配置osx系统代理" > 配 置 OSX系 统 代 理 < / h3 >
< ul >
< li > 在 wifi高 级 设 置 中 , 配 置 http代 理 即 可 < / li >
< / ul >
< p > < img src = "https://zos.alipayobjects.com/rmsportal/vduwhobSTypTfgniBvoa.png" width = "500" > < / p >
< h3 id = "配置浏览器http代理" > 配 置 浏 览 器 HTTP代 理 < / h3 >
< ul >
< li > 以 Chrome的 < a href = "https://chrome.google.com/webstore/detail/padekgcemlokbadohgkifijomclgjgif" target = "_blank" > SwitchyOmega插 件 < / a > 为 例 < / li >
< / ul >
< p > < img src = "https://zos.alipayobjects.com/rmsportal/jIPZrKmqXRaSledQeJUJ.png" width = "500" > < / p >
< h3 id = "ios系统信任ca证书" > iOS系 统 信 任 CA证 书 < / h3 >
< ul >
< li > 点 击 web ui中 的 < em > Root CA< / em > , 按 提 示 扫 描 二 维 码 即 可 安 装 < / li >
< / ul >
< p > < img src = "https://zos.alipayobjects.com/rmsportal/BrugmMelGVysLDOIBblj.png" width = "260" > < / p >
< h3 id = "ios--103信任ca证书" > iOS > = 10.3信 任 CA证 书 < / h3 >
< ul >
< li > 除 了 上 述 证 书 安 装 过 程 , 还 需 要 在 < em > 设 置 -> 通 用 -> 关 于 本 机 -> 证 书 信 任 设 置 < / em > 中 把 AnyProxy证 书 的 开 关 打 开 , 否 则 safari将 报 错 。 < / li >
< / ul >
< p > < img src = "https://zos.alipayobjects.com/rmsportal/hVWkXHrzHmOKOtCKGUWx.png" width = "500" > < / p >
< h3 id = "配置iosandroid系统代理" > 配 置 iOS/Android系 统 代 理 < / h3 >
< ul >
< li > < p > 代 理 服 务 器 都 在 wifi设 置 中 配 置 < / p >
< / li >
< li > < p > iOS HTTP代 理 配 置 < / p >
< / li >
< / ul >
< p > < img src = "https://zos.alipayobjects.com/rmsportal/tLGqIozhffTccUgPakuw.png" width = "260" > < / p >
< ul >
< li > Android HTTP代 理 配 置 < / li >
< / ul >
< p > < img src = "https://zos.alipayobjects.com/rmsportal/YQtbQYVNuOszZGdAOauU.png" width = "260" > < / p >
< h1 id = "faq" > FAQ< / h1 >
< h4 id = "q-为什么https请求不能进入处理函数?" > Q: 为 什 么 https请 求 不 能 进 入 处 理 函 数 ? < / h4 >
< p > A: 以 下 任 意 一 项 都 能 用 来 改 变 https的 处 理 特 性 : < / p >
< pre > < code > 1. 命 令 行 启 动 AnyProxy时 配 置 `--intercept`参 数 , 按 npm模 块 启 动 时 配 置 `forceProxyHttps`参 数 , 所 有 Https请 求 都 会 被 替 换 证 书 并 解 析
2. 规 则 文 件 内 提 供 `beforeDealHttpsRequest`方 法 , 返 回 *true* 的 https请 求 会 被 解 析
< / code > < / pre > < h4 id = "q-提示-function-is-not-yieldable" > Q: 提 示 < em > function is not yieldable< / em > < / h4 >
< ul >
< li > A: 规 则 模 块 是 用 < a href = "https://www.npmjs.com/package/co" target = "_blank" > co< / a > 驱 动 的 , 函 数 需 要 满 足 yieldable。 可 以 使 用 generator方 法 或 是 返 回 Promise。 < / li >
< / ul >
< h4 id = "q-the-connection-is-not-private" > Q: The connection is not private< / h4 >
< p > 当 访 问 特 定 的 HTTPS站 点 , AnyProxy会 提 示 该 站 点 不 是 一 个 安 全 的 网 站 , 这 通 常 是 因 为 站 点 的 证 书 设 置 不 能 被 正 确 识 别 导 致 的 ( 比 如 , 站 点 的 证 书 是 自 签 发 的 ) 。 如 果 您 信 任 该 网 站 , 可 以 用 以 下 方 式 来 继 续 访 问 : < / p >
< ul >
< li > < p > 命 令 行 直 接 启 动 < / p >
< p > 通 过 启 动 参 数 < code > --ignore-unauthorized-ssl< / code > 来 忽 略 证 书 认 证 的 错 误 。 需 要 注 意 的 是 , 该 参 数 是 全 局 生 效 的 , 如 果 你 在 此 期 间 访 问 了 其 他 未 知 的 网 站 , 他 们 的 证 书 问 题 也 会 被 忽 略 , 这 可 能 会 带 来 安 全 隐 患 。 < / p >
< pre > < code class = "lang-bash" > anyproxy -i --ignore-unauthorized-ssl
< / code > < / pre >
< / li >
< li > < p > 在 Nodejs代 码 中 启 动 < / p >
< p > 在 构 造 AnyProxy实 例 的 时 候 , 传 入 参 数 < code > dangerouslyIgnoreUnauthorized:true< / code > , 如 下 : < / p >
< pre > < code class = "lang-js" > < span class = "hljs-keyword" > const< / span > options = {
...,
dangerouslyIgnoreUnauthorized: < span class = "hljs-literal" > true< / span >
};
< span class = "hljs-keyword" > const< / span > anyproxyIns = < span class = "hljs-keyword" > new< / span > AnyProxy.ProxyCore(options);
anyproxyIns.start();
< / code > < / pre >
< p > < em > 通 过 这 种 方 式 初 始 化 的 AnyProxy, 其 配 置 也 是 全 局 性 的 , 所 有 网 站 的 证 书 问 题 都 会 被 忽 略 < / em > < / p >
< / li >
< li > < p > 通 过 自 定 义 的 Rule来 修 改 < / p >
< p > 我 们 自 然 也 可 以 借 助 自 定 义 的 Rule来 实 现 这 个 效 果 , 而 且 我 们 还 可 以 控 制 到 只 允 许 指 定 网 址 的 证 书 错 误 , 对 不 在 列 表 的 网 址 , 进 行 证 书 的 强 验 证 。 < / p >
< pre > < code class = "lang-js" > < span class = "hljs-built_in" > module< / span > .exports = {
*beforeSendRequest(requestDetail) {
< span class = "hljs-keyword" > if< / span > (requestDetail.url.indexOf(< span class = "hljs-string" > ' https://the-site-you-know.com' < / span > ) === < span class = "hljs-number" > 0< / span > ) {
< span class = "hljs-keyword" > const< / span > newRequestOptions = requestDetail.requestOptions;
< span class = "hljs-comment" > // 设 置 属 性 rejectUnauthorized 为 false< / span >
newRequestOptions.rejectUnauthorized = < span class = "hljs-literal" > false< / span > ;
< span class = "hljs-keyword" > return< / span > {
requestOptions: newRequestOptions
};
}
},
};
< / code > < / pre >
< / li >
< / ul >
< / section >
< / div >
< div class = "search-results" >
< div class = "has-results" >
< h1 class = "search-results-title" > < span class = 'search-results-count' > < / span > results matching "< span class = 'search-query' > < / span > "< / h1 >
< ul class = "search-results-list" > < / ul >
< / div >
< div class = "no-results" >
< h1 class = "search-results-title" > No results matching "< span class = 'search-query' > < / span > "< / h1 >
< / div >
< / div >
< / div >
< / div >
< / div >
< / div >
< a href = "./#快速开始" class = "navigation navigation-next navigation-unique" aria-label = "Next page: 快速开始" >
< i class = "fa fa-angle-right" > < / i >
< / a >
< / div >
< script >
var gitbook = gitbook || [];
gitbook.push(function() {
2017-12-01 21:58:32 +08:00
gitbook.page.hasChanged({"page":{"title":"简介","level":"1.1","depth":1,"next":{"title":"快速开始","level":"1.2","depth":1,"anchor":"#快速开始","path":"README.md","ref":"README.md#快速开始","articles":[{"title":"安装","level":"1.2.1","depth":2,"anchor":"#安装","path":"README.md","ref":"README.md#安装","articles":[]},{"title":"启动","level":"1.2.2","depth":2,"anchor":"#启动","path":"README.md","ref":"README.md#启动","articles":[]},{"title":"其他命令","level":"1.2.3","depth":2,"anchor":"#其他命令","path":"README.md","ref":"README.md#其他命令","articles":[]},{"title":"作为npm模块启动","level":"1.2.4","depth":2,"anchor":"#作为npm模块使用","path":"README.md","ref":"README.md#作为npm模块使用","articles":[]}]},"dir":"ltr"},"config":{"plugins":[],"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"pluginsConfig":{"livereload":{},"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"theme":"default","author":"AnyProxy","pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"variables":{},"title":"AnyProxy","language":"cn","gitbook":"*","description":"A fully configurable http/https proxy in NodeJS"},"file":{"path":"README.md","mtime":"2017-12-01T13:58:00.991Z","type":"markdown"},"gitbook":{"version":"3.2.2","time":"2017-12-01T13:58:02.250Z"},"basePath":".","book":{"language":"cn"}});
2017-12-01 21:30:49 +08:00
});
< / script >
< / div >
< script src = "../gitbook/gitbook.js" > < / script >
< script src = "../gitbook/theme.js" > < / script >
< script src = "../gitbook/gitbook-plugin-livereload/plugin.js" > < / script >
< script src = "../gitbook/gitbook-plugin-search/search-engine.js" > < / script >
< script src = "../gitbook/gitbook-plugin-search/search.js" > < / script >
< script src = "../gitbook/gitbook-plugin-lunr/lunr.min.js" > < / script >
< script src = "../gitbook/gitbook-plugin-lunr/search-lunr.js" > < / script >
< script src = "../gitbook/gitbook-plugin-sharing/buttons.js" > < / script >
< script src = "../gitbook/gitbook-plugin-fontsettings/fontsettings.js" > < / script >
< / body >
< / html >