mirror of
https://github.com/alibaba/anyproxy.git
synced 2025-04-21 16:34:20 +00:00
736 lines
42 KiB
HTML
736 lines
42 KiB
HTML
<!doctype html>
|
||
<html>
|
||
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, minimal-ui">
|
||
<title>AnyProxy</title>
|
||
<link type="text/css" rel="stylesheet" href="assets/css/github-markdown.css">
|
||
<link type="text/css" rel="stylesheet" href="assets/css/pilcrow.css">
|
||
<link type="text/css" rel="stylesheet" href="assets/css/atom-one-light.css" />
|
||
<link type="text/css" rel="stylesheet" href="assets/css/custom.css" />
|
||
</head>
|
||
|
||
<body>
|
||
<a href="https://github.com/alibaba/anyproxy/tree/4.x" target="_blank">
|
||
<img style="position: fixed; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/a6677b08c955af8400f44c6298f40e7d19cc5b2d/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f677261795f3664366436642e706e67"
|
||
alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png">
|
||
</a>
|
||
|
||
<article class="markdown-body">
|
||
<div class="toc-container" id="j_toc"><ul class="nav nav-list">
|
||
<li class="sidebar-header-1"><a href="#anyproxy">AnyProxy</a></li>
|
||
<li class="sidebar-header-2"><a href="#快速上手">快速上手</a></li>
|
||
<li class="sidebar-header-3"><a href="#安装">安装</a></li>
|
||
<li class="sidebar-header-3"><a href="#启动">启动</a></li>
|
||
<li class="sidebar-header-3"><a href="#其他命令">其他命令</a></li>
|
||
<li class="sidebar-header-2"><a href="#代理https请求">代理https请求</a></li>
|
||
<li class="sidebar-header-2"><a href="#规则模块(rule)">规则模块(Rule)</a></li>
|
||
<li class="sidebar-header-3"><a href="#开发示例">开发示例</a></li>
|
||
<li class="sidebar-header-3"><a href="#处理流程">处理流程</a></li>
|
||
<li class="sidebar-header-3"><a href="#如何引用">如何引用</a></li>
|
||
<li class="sidebar-header-3"><a href="#接口详解">接口详解</a></li>
|
||
<li class="sidebar-header-4"><a href="#summary()">summary()</a></li>
|
||
<li class="sidebar-header-4"><a href="#beforesendrequest(requestdetail)">beforeSendRequest(requestDetail)</a></li>
|
||
<li class="sidebar-header-4"><a href="#beforesendresponse(requestdetail,-responsedetail)">beforeSendResponse(requestDetail, responseDetail)</a></li>
|
||
<li class="sidebar-header-4"><a href="#beforedealhttpsrequest(requestdetail)">beforeDealHttpsRequest(requestDetail)</a></li>
|
||
<li class="sidebar-header-3"><a href="#faq">FAQ</a></li>
|
||
<li class="sidebar-header-2"><a href="#规则模块样例">规则模块样例</a></li>
|
||
<li class="sidebar-header-3"><a href="#使用本地数据">使用本地数据</a></li>
|
||
<li class="sidebar-header-3"><a href="#修改请求头">修改请求头</a></li>
|
||
<li class="sidebar-header-3"><a href="#修改请求数据">修改请求数据</a></li>
|
||
<li class="sidebar-header-3"><a href="#修改请求的目标地址">修改请求的目标地址</a></li>
|
||
<li class="sidebar-header-3"><a href="#修改请求协议">修改请求协议</a></li>
|
||
<li class="sidebar-header-3"><a href="#修改返回状态码">修改返回状态码</a></li>
|
||
<li class="sidebar-header-3"><a href="#修改返回头">修改返回头</a></li>
|
||
<li class="sidebar-header-3"><a href="#修改返回内容并延迟">修改返回内容并延迟</a></li>
|
||
<li class="sidebar-header-2"><a href="#作为npm模块使用">作为npm模块使用</a></li>
|
||
<li class="sidebar-header-2"><a href="#关于anyproxy">关于AnyProxy</a></li>
|
||
<li class="sidebar-header-2"><a href="#配置帮助">配置帮助</a></li>
|
||
<li class="sidebar-header-3"><a href="#osx系统信任ca证书">OSX系统信任CA证书</a></li>
|
||
<li class="sidebar-header-3"><a href="#windows系统信任ca证书">Windows系统信任CA证书</a></li>
|
||
<li class="sidebar-header-3"><a href="#配置osx系统代理">配置OSX系统代理</a></li>
|
||
<li class="sidebar-header-3"><a href="#配置浏览器http代理">配置浏览器HTTP代理</a></li>
|
||
<li class="sidebar-header-3"><a href="#配置ios/android系统代理">配置iOS/Android系统代理</a></li>
|
||
</ul>
|
||
</div>
|
||
<div class="main-content"><h1 id="anyproxy"><a class="header-link" href="#anyproxy"></a>AnyProxy</h1>
|
||
<blockquote>
|
||
<p>本文档的适用范围是AnyProxy 4.0,此版本当前正在beta中,欢迎提供反馈</p>
|
||
</blockquote>
|
||
<p>AnyProxy是一个开放式的HTTP代理服务器。</p>
|
||
<p>Github主页:<a href="https://github.com/alibaba/anyproxy/tree/4.x">https://github.com/alibaba/anyproxy/tree/4.x</a></p>
|
||
<p>主要特性包括:</p>
|
||
<ul class="list">
|
||
<li>基于Node.js,开放二次开发能力,允许自定义请求处理逻辑</li>
|
||
<li>支持Https的解析</li>
|
||
<li>提供GUI界面,用以观察请求</li>
|
||
</ul>
|
||
<p>相比3.x版本,AnyProxy 4.0的主要变化:</p>
|
||
<ul class="list">
|
||
<li>规则文件(Rule)全面支持Promise和Generator</li>
|
||
<li>简化了规则文件内的接口</li>
|
||
<li>Web版界面重构</li>
|
||
</ul>
|
||
<p class="img-container"><img src="https://zos.alipayobjects.com/rmsportal/SqVntpzmscXPbSzfcGcr.png" width="500" /></p>
|
||
<h2 id="快速上手"><a class="header-link" href="#快速上手"></a>快速上手</h2>
|
||
<h3 id="安装"><a class="header-link" href="#安装"></a>安装</h3>
|
||
<pre class="hljs"><code>npm install -g anyproxy@beta <span class="hljs-comment">#本文档对应的AnyProxy为4.0Beta版</span></code></pre><h3 id="启动"><a class="header-link" href="#启动"></a>启动</h3>
|
||
<ul class="list">
|
||
<li>命令行启动AnyProxy,默认端口号8001</li>
|
||
</ul>
|
||
<pre class="hljs"><code>anyproxy</code></pre><ul class="list">
|
||
<li>启动后将终端http代理服务器配置为127.0.0.1:8001即可</li>
|
||
<li>访问<a href="http://127.0.0.1:8002">http://127.0.0.1:8002</a> ,web界面上能看到所有的请求信息</li>
|
||
</ul>
|
||
<h3 id="其他命令"><a class="header-link" href="#其他命令"></a>其他命令</h3>
|
||
<ul class="list">
|
||
<li>配置启动端口,如1080端口启动</li>
|
||
</ul>
|
||
<pre class="hljs"><code>anyproxy --port 1080</code></pre><h2 id="代理https请求"><a class="header-link" href="#代理https请求"></a>代理https请求</h2>
|
||
<ul class="list">
|
||
<li>AnyProxy默认不对https请求做处理,如需看到明文信息,需要配置CA证书</li>
|
||
</ul>
|
||
<blockquote>
|
||
<p>解析https请求的原理是中间人攻击(man-in-the-middle),用户必须信任AnyProxy生成的CA证书,才能进行后续流程</p>
|
||
</blockquote>
|
||
<ul class="list">
|
||
<li>生成证书并解析所有https请求</li>
|
||
</ul>
|
||
<pre class="hljs"><code>anyproxy-ca <span class="hljs-comment">#生成rootCA证书,生成后需要手动信任</span>
|
||
anyproxy --intercept <span class="hljs-comment">#启动AnyProxy,并解析所有https请求</span></code></pre><ul class="list">
|
||
<li><a href="#osx系统信任ca证书">附录:如何信任CA证书</a></li>
|
||
</ul>
|
||
<h2 id="规则模块(rule)"><a class="header-link" href="#规则模块(rule)"></a>规则模块(Rule)</h2>
|
||
<p>AnyProxy提供了二次开发的能力,你可以用js编写自己的规则模块(rule),来自定义网络请求的处理逻辑。</p>
|
||
<blockquote>
|
||
<p>注意:引用规则前,请务必确保文件来源可靠,以免发生安全问题</p>
|
||
</blockquote>
|
||
<p>规则模块的能力范围包括:</p>
|
||
<ul class="list">
|
||
<li>拦截并修改正在发送的请求<ul class="list">
|
||
<li>可修改内容包括请求头(request header),请求体(request body),甚至是请求的目标地址等</li>
|
||
</ul>
|
||
</li>
|
||
<li>拦截并修改服务端响应<ul class="list">
|
||
<li>可修改的内容包括http状态码(status code)、响应头(response header)、响应内容等</li>
|
||
</ul>
|
||
</li>
|
||
<li>拦截https请求,对内容做修改<ul class="list">
|
||
<li>本质是中间人攻击(man-in-the-middle attack),需要客户端提前信任AnyProxy生成的CA</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<h3 id="开发示例"><a class="header-link" href="#开发示例"></a>开发示例</h3>
|
||
<ul class="list">
|
||
<li><p>举例</p>
|
||
<ul class="list">
|
||
<li>需要编写一个规则模块,在 GET <a href="http://httpbin.org/user-agent">http://httpbin.org/user-agent</a> 的返回值里加上测试信息,并延迟5秒返回</li>
|
||
</ul>
|
||
</li>
|
||
<li><p>Step 1,编写规则</p>
|
||
<pre class="hljs"><code><span class="hljs-comment">// file: sample.js</span>
|
||
<span class="hljs-built_in">module</span>.exports = {
|
||
summary() { <span class="hljs-keyword">return</span> <span class="hljs-string">'a rule to modify response'</span>; },
|
||
*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>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =></span> {
|
||
setTimeout(<span class="hljs-function"><span class="hljs-params">()</span> =></span> { <span class="hljs-comment">// delay</span>
|
||
resolve({ <span class="hljs-attr">response</span>: newResponse });
|
||
}, <span class="hljs-number">5000</span>);
|
||
});
|
||
}
|
||
},
|
||
};</code></pre></li>
|
||
<li><p>Step 2, 启动AnyProxy,加载规则</p>
|
||
<ul class="list">
|
||
<li>运行 <code>anyproxy --rule sample.js</code></li>
|
||
</ul>
|
||
</li>
|
||
<li><p>Step 3, 测试规则</p>
|
||
<ul class="list">
|
||
<li><p>用curl测试 </p>
|
||
<pre class="hljs"><code>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">http://httpbin.org/user-agent</a> </p>
|
||
</li>
|
||
<li><p>经过代理服务器后,期望的返回如下</p>
|
||
</li>
|
||
</ul>
|
||
<pre class="hljs"><code>{
|
||
<span class="hljs-string">"user-agent"</span>: <span class="hljs-string">"curl/7.43.0"</span>
|
||
}
|
||
- AnyProxy Hacked!</code></pre></li>
|
||
<li><p>Step 4, 查看请求信息</p>
|
||
<ul class="list">
|
||
<li>浏览器访问<a href="http://127.0.0.1:8002">http://127.0.0.1:8002</a> ,界面上能看到刚才的请求信息</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<h3 id="处理流程"><a class="header-link" href="#处理流程"></a>处理流程</h3>
|
||
<ul class="list">
|
||
<li><p>当http请求经过代理服务器时,代理服务器的处理流程是:</p>
|
||
<ul class="list">
|
||
<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 class="list">
|
||
<li>调用规则模块<code>beforeDealHttpsRequest</code>方法,如果返回<code>true</code>,会明文解析这个请求,其他请求不处理</li>
|
||
<li>被明文解析后的https请求,处理流程同http一致。未明文解析请求不会再进入规则模块做处理。</li>
|
||
</ul>
|
||
</li>
|
||
<li><p>完整的请求处理流程如下,供参考</p>
|
||
</li>
|
||
</ul>
|
||
<p class="img-container"><img src="https://zos.alipayobjects.com/rmsportal/TWyNuSJtEZBdrdcOMRjE.png" width="550" /></p>
|
||
<h3 id="如何引用"><a class="header-link" href="#如何引用"></a>如何引用</h3>
|
||
<p>如下几种方案都可以用来引用规则模块:</p>
|
||
<ul class="list">
|
||
<li>使用本地路径<pre class="hljs"><code>anyproxy --rule ./rule.js</code></pre></li>
|
||
<li><p>使用在线地址</p>
|
||
<pre class="hljs"><code>anyproxy --rule https://sample.com/rule.js</code></pre></li>
|
||
<li><p>使用npm包</p>
|
||
<ul class="list">
|
||
<li>AnyProxy使用<code>require()</code>加载本地规则,你可以在参数里传入一个本地的npm包路径,或是某个全局安装的npm包</li>
|
||
</ul>
|
||
<pre class="hljs"><code>anyproxy --rule ./myRulePkg/ <span class="hljs-comment">#本地包</span>
|
||
npm i -g myRulePkg && anyproxy --rule myRulePkg <span class="hljs-comment">#全局包</span></code></pre></li>
|
||
</ul>
|
||
<h3 id="接口详解"><a class="header-link" href="#接口详解"></a>接口详解</h3>
|
||
<p>规则模块应该符合cmd规范,一个典型的规则模块代码结构如下</p>
|
||
<pre class="hljs"><code><span class="hljs-built_in">module</span>.exports = {
|
||
summary() { <span class="hljs-keyword">return</span> <span class="hljs-string">'my customized rule for AnyProxy'</span>; },
|
||
*beforeSendRequest(requestDetail) { <span class="hljs-comment">/* ... */</span> },
|
||
*beforeSendResponse(requestDetail, responseDetail) { <span class="hljs-comment">/* ... */</span> },
|
||
*beforeDealHttpsRequest(requestDetail) { <span class="hljs-comment">/* ... */</span> }
|
||
};</code></pre><h4 id="summary()"><a class="header-link" href="#summary()"></a>summary()</h4>
|
||
<ul class="list">
|
||
<li>返回规则模块介绍,用于AnyProxy提示用户</li>
|
||
</ul>
|
||
<h4 id="beforesendrequest(requestdetail)"><a class="header-link" href="#beforesendrequest(requestdetail)"></a>beforeSendRequest(requestDetail)</h4>
|
||
<ul class="list">
|
||
<li>AnyProxy向服务端发送请求前,会调用<code>beforeSendRequest</code>,并带上参数<code>requestDetail</code></li>
|
||
<li><code>requestDetail</code> <ul class="list">
|
||
<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">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> 时,requestDetail参数内容大致如下</p>
|
||
<pre class="hljs"><code>{
|
||
<span class="hljs-attr">protocol</span>: <span class="hljs-string">'http'</span>,
|
||
<span class="hljs-attr">url</span>: <span class="hljs-string">'http://anyproxy.io/'</span>,
|
||
<span class="hljs-attr">requestOptions</span>: {
|
||
<span class="hljs-attr">hostname</span>: <span class="hljs-string">'anyproxy.io'</span>,
|
||
<span class="hljs-attr">port</span>: <span class="hljs-number">80</span>,
|
||
<span class="hljs-attr">path</span>: <span class="hljs-string">'/'</span>,
|
||
<span class="hljs-attr">method</span>: <span class="hljs-string">'GET'</span>,
|
||
<span class="hljs-attr">headers</span>: {
|
||
<span class="hljs-attr">Host</span>: <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>
|
||
}
|
||
},
|
||
<span class="hljs-attr">requestData</span>: <span class="hljs-string">'...'</span>,
|
||
<span class="hljs-attr">_req</span>: { <span class="hljs-comment">/* ... */</span>}
|
||
}</code></pre></li>
|
||
<li><p>以下几种返回都是合法的</p>
|
||
<ul class="list">
|
||
<li>不做任何处理,返回null</li>
|
||
</ul>
|
||
<pre class="hljs"><code><span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;</code></pre><ul class="list">
|
||
<li>修改请求协议,如强制改用https发起请求</li>
|
||
</ul>
|
||
<pre class="hljs"><code><span class="hljs-keyword">return</span> {
|
||
<span class="hljs-attr">protocol</span>: <span class="hljs-string">'https'</span>
|
||
};</code></pre><ul class="list">
|
||
<li>修改请求参数</li>
|
||
</ul>
|
||
<pre class="hljs"><code><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> {
|
||
<span class="hljs-attr">requestOptions</span>: newOption
|
||
};</code></pre><ul class="list">
|
||
<li>修改请求body</li>
|
||
</ul>
|
||
<pre class="hljs"><code><span class="hljs-keyword">return</span> {
|
||
<span class="hljs-attr">requestData</span>: <span class="hljs-string">'my new request data'</span>
|
||
<span class="hljs-comment">//这里也可以同时加上requestOptions</span>
|
||
};</code></pre><ul class="list">
|
||
<li>直接返回客户端,不再发起请求</li>
|
||
</ul>
|
||
<pre class="hljs"><code><span class="hljs-keyword">return</span> {
|
||
<span class="hljs-attr">statusCode</span>: <span class="hljs-number">200</span>,
|
||
<span class="hljs-attr">header</span>: { <span class="hljs-string">'content-type'</span>: <span class="hljs-string">'text/html'</span> },
|
||
<span class="hljs-attr">body</span>: <span class="hljs-string">'this could be a <string> or <buffer>'</span>
|
||
};</code></pre></li>
|
||
</ul>
|
||
<h4 id="beforesendresponse(requestdetail,-responsedetail)"><a class="header-link" href="#beforesendresponse(requestdetail,-responsedetail)"></a>beforeSendResponse(requestDetail, responseDetail)</h4>
|
||
<ul class="list">
|
||
<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 class="list">
|
||
<li><code>response</code> {object} 服务端的返回信息,包括<code>statusCode</code> <code>header</code> <code>body</code>三个字段</li>
|
||
<li><code>_res</code> {object} 原始的服务端返回对象</li>
|
||
</ul>
|
||
</li>
|
||
<li>举例,请求www.qq.com时,responseDetail参数内容大致如下</li>
|
||
<li><p>以下几种返回都是合法的</p>
|
||
<ul class="list">
|
||
<li>不做任何处理,返回null</li>
|
||
</ul>
|
||
<pre class="hljs"><code><span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;</code></pre><ul class="list">
|
||
<li>修改返回的状态码</li>
|
||
</ul>
|
||
<pre class="hljs"><code><span class="hljs-keyword">var</span> newResponse = <span class="hljs-built_in">Object</span>.assign({}, responseDetail.reponse);
|
||
newResponse.statusCode = <span class="hljs-number">404</span>;
|
||
<span class="hljs-keyword">return</span> {
|
||
<span class="hljs-attr">response</span>: newResponse
|
||
};</code></pre><ul class="list">
|
||
<li>修改返回的内容</li>
|
||
</ul>
|
||
<pre class="hljs"><code><span class="hljs-keyword">var</span> newResponse = <span class="hljs-built_in">Object</span>.assign({}, responseDetail.reponse);
|
||
newResponse.body += <span class="hljs-string">'--from anyproxy--'</span>;
|
||
<span class="hljs-keyword">return</span> {
|
||
<span class="hljs-attr">response</span>: newResponse
|
||
};</code></pre></li>
|
||
</ul>
|
||
<h4 id="beforedealhttpsrequest(requestdetail)"><a class="header-link" href="#beforedealhttpsrequest(requestdetail)"></a>beforeDealHttpsRequest(requestDetail)</h4>
|
||
<ul class="list">
|
||
<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 class="list">
|
||
<li><code>host</code> {string} 请求目标的Host,受制于协议,这里无法获取完整url</li>
|
||
<li><code>_req</code> {object} 请求的原始request</li>
|
||
</ul>
|
||
</li>
|
||
<li>返回值<ul class="list">
|
||
<li><code>true</code>或者<code>false</code>,是否需要AnyProxy解析https</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<h3 id="faq"><a class="header-link" href="#faq"></a>FAQ</h3>
|
||
<ul class="list">
|
||
<li>Q: 为什么https请求不能进入处理函数?</li>
|
||
<li>A: 请确认规则文件内是否配置了<code>beforeDealHttpsRequest</code>方法,或启动时是否使用了<code>--intercept</code>参数</li>
|
||
</ul>
|
||
<h2 id="规则模块样例"><a class="header-link" href="#规则模块样例"></a>规则模块样例</h2>
|
||
<ul class="list">
|
||
<li>这里提供一些样例,来讲解如何开发规则模块,你可以直接通过 <code>anyproxy --rule http://....js</code> 来加载这些样例模块</li>
|
||
<li>用curl发请求测试的方法如下<ul class="list">
|
||
<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="使用本地数据"><a class="header-link" href="#使用本地数据"></a>使用本地数据</h3>
|
||
<ul class="list">
|
||
<li>拦截发送到 <a href="http://httpbin.org">http://httpbin.org</a> 的请求,使用本地数据代替服务端返回</li>
|
||
</ul>
|
||
<pre class="hljs"><code>anyproxy --rule https://raw.githubusercontent.com/alibaba/anyproxy/4.x/rule_sample/sample_use_local_response.js</code></pre><pre class="hljs"><code><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 = {
|
||
<span class="hljs-attr">statusCode</span>: <span class="hljs-number">200</span>,
|
||
<span class="hljs-attr">header</span>: { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span> },
|
||
<span class="hljs-attr">body</span>: <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> {
|
||
<span class="hljs-attr">response</span>: localResponse
|
||
};
|
||
}
|
||
},
|
||
};</code></pre><h3 id="修改请求头"><a class="header-link" href="#修改请求头"></a>修改请求头</h3>
|
||
<ul class="list">
|
||
<li>修改发送到 httpbin.org 的user-agent</li>
|
||
</ul>
|
||
<pre class="hljs"><code>anyproxy --rule https://raw.githubusercontent.com/alibaba/anyproxy/4.x/rule_sample/sample_modify_request_header.js</code></pre><pre class="hljs"><code><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> {
|
||
<span class="hljs-attr">requestOptions</span>: newRequestOptions
|
||
};
|
||
}
|
||
},
|
||
};</code></pre><h3 id="修改请求数据"><a class="header-link" href="#修改请求数据"></a>修改请求数据</h3>
|
||
<ul class="list">
|
||
<li>修改发送到 <a href="http://httpbin.org/post">http://httpbin.org/post</a> 的post数据</li>
|
||
</ul>
|
||
<pre class="hljs"><code>anyproxy --rule https://raw.githubusercontent.com/alibaba/anyproxy/4.x/rule_sample/sample_modify_request_data.js</code></pre><pre class="hljs"><code><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 = {
|
||
*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> {
|
||
<span class="hljs-attr">requestData</span>: <span class="hljs-string">'i-am-anyproxy-modified-post-data'</span>
|
||
};
|
||
}
|
||
},
|
||
};</code></pre><h3 id="修改请求的目标地址"><a class="header-link" href="#修改请求的目标地址"></a>修改请求的目标地址</h3>
|
||
<ul class="list">
|
||
<li>把所有发送到 <a href="http://httpbin.org/">http://httpbin.org/</a> 的请求全部改到 <a href="http://httpbin.org/user-agent">http://httpbin.org/user-agent</a></li>
|
||
</ul>
|
||
<pre class="hljs"><code>anyproxy --rule https://raw.githubusercontent.com/alibaba/anyproxy/4.x/rule_sample/sample_modify_request_path.js</code></pre><pre class="hljs"><code><span class="hljs-comment">/*
|
||
sample:
|
||
redirect all httpbin.org requests to http://httpbin.org/user-agent
|
||
test:
|
||
curl http://httpbin.org/any-path --proxy http://127.0.0.1:8001
|
||
expected response:
|
||
{ "user-agent": "curl/7.43.0" }
|
||
*/</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.path = <span class="hljs-string">'/user-agent'</span>;
|
||
newRequestOptions.method = <span class="hljs-string">'GET'</span>;
|
||
<span class="hljs-keyword">return</span> {
|
||
<span class="hljs-attr">requestOptions</span>: newRequestOptions
|
||
};
|
||
}
|
||
},
|
||
};</code></pre><h3 id="修改请求协议"><a class="header-link" href="#修改请求协议"></a>修改请求协议</h3>
|
||
<ul class="list">
|
||
<li>把用http协议请求的 <a href="http://httpbin.org">http://httpbin.org</a> 改成https并发送</li>
|
||
</ul>
|
||
<pre class="hljs"><code>anyproxy --rule https://raw.githubusercontent.com/alibaba/anyproxy/4.x/rule_sample/sample_modify_request_protocol.js</code></pre><pre class="hljs"><code><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> {
|
||
<span class="hljs-attr">protocol</span>: <span class="hljs-string">'https'</span>,
|
||
<span class="hljs-attr">requestOptions</span>: newOption
|
||
};
|
||
}
|
||
}
|
||
};</code></pre><h3 id="修改返回状态码"><a class="header-link" href="#修改返回状态码"></a>修改返回状态码</h3>
|
||
<ul class="list">
|
||
<li>把 所有<a href="http://httpbin.org">http://httpbin.org</a> 的返回状态码都改成404</li>
|
||
</ul>
|
||
<pre class="hljs"><code>anyproxy --rule https://raw.githubusercontent.com/alibaba/anyproxy/4.x/rule_sample/sample_modify_response_statuscode.js</code></pre><pre class="hljs"><code><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> {
|
||
<span class="hljs-attr">response</span>: newResponse
|
||
};
|
||
}
|
||
}
|
||
};</code></pre><h3 id="修改返回头"><a class="header-link" href="#修改返回头"></a>修改返回头</h3>
|
||
<ul class="list">
|
||
<li>在 <a href="http://httpbin.org/user-agent">http://httpbin.org/user-agent</a> 的返回头里加上 X-Proxy-By:AnyProxy</li>
|
||
</ul>
|
||
<pre class="hljs"><code>anyproxy --rule https://raw.githubusercontent.com/alibaba/anyproxy/4.x/rule_sample/sample_modify_response_header.js</code></pre><pre class="hljs"><code><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> {
|
||
<span class="hljs-attr">response</span>: newResponse
|
||
};
|
||
}
|
||
}
|
||
};</code></pre><h3 id="修改返回内容并延迟"><a class="header-link" href="#修改返回内容并延迟"></a>修改返回内容并延迟</h3>
|
||
<ul class="list">
|
||
<li>在 <a href="http://httpbin.org/user-agent">http://httpbin.org/user-agent</a> 的返回最后追加AnyProxy的签名,并延迟5秒</li>
|
||
</ul>
|
||
<pre class="hljs"><code>anyproxy --rule https://raw.githubusercontent.com/alibaba/anyproxy/4.x/rule_sample/sample_modify_response_data.js</code></pre><pre class="hljs"><code><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 = {
|
||
summary() { <span class="hljs-keyword">return</span> <span class="hljs-string">'a rule to modify response'</span>; },
|
||
*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>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =></span> {
|
||
setTimeout(<span class="hljs-function"><span class="hljs-params">()</span> =></span> { <span class="hljs-comment">// delay the response for 5s</span>
|
||
resolve({ <span class="hljs-attr">response</span>: newResponse });
|
||
}, <span class="hljs-number">5000</span>);
|
||
});
|
||
}
|
||
},
|
||
};</code></pre><h2 id="作为npm模块使用"><a class="header-link" href="#作为npm模块使用"></a>作为npm模块使用</h2>
|
||
<p>AnyProxy可以作为一个npm模块使用,整合进其他工具。
|
||
注意:如要启用https解析,请在代理服务器启动前自行调用<code>AnyProxy.utils.certMgr</code>相关方法生成证书,并引导用户信任安装。</p>
|
||
<ul class="list">
|
||
<li>引入</li>
|
||
</ul>
|
||
<pre class="hljs"><code>npm i anyproxy --save</code></pre><ul class="list">
|
||
<li>使用举例</li>
|
||
</ul>
|
||
<pre class="hljs"><code><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 = {
|
||
<span class="hljs-attr">port</span>: <span class="hljs-number">8001</span>,
|
||
<span class="hljs-attr">rule</span>: <span class="hljs-built_in">require</span>(<span class="hljs-string">'myRuleModule'</span>),
|
||
<span class="hljs-attr">webInterface</span>: {
|
||
<span class="hljs-attr">enable</span>: <span class="hljs-literal">true</span>,
|
||
<span class="hljs-attr">webPort</span>: <span class="hljs-number">8002</span>,
|
||
<span class="hljs-attr">wsPort</span>: <span class="hljs-number">8003</span>,
|
||
},
|
||
<span class="hljs-attr">throttle</span>: <span class="hljs-number">10000</span>,
|
||
<span class="hljs-attr">forceProxyHttps</span>: <span class="hljs-literal">false</span>,
|
||
<span class="hljs-attr">silent</span>: <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 class="list">
|
||
<li><p>Class: AnyProxy.proxyServer</p>
|
||
<ul class="list">
|
||
<li><p>创建代理服务器</p>
|
||
<pre class="hljs"><code><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 class="list">
|
||
<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 class="list">
|
||
<li><code>enable</code> {boolean} 是否启用web版界面,默认<code>false</code></li>
|
||
<li><code>webPort</code> {number} web版界面端口号,默认<code>8002</code></li>
|
||
<li><code>wsPort</code> {number} web版界面的ws端口号,默认<code>8003</code></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li><p>Event: <code>ready</code></p>
|
||
<ul class="list">
|
||
<li>代理服务器启动完成</li>
|
||
<li>示例</li>
|
||
</ul>
|
||
<pre class="hljs"><code>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 class="list">
|
||
<li>代理服务器发生错误</li>
|
||
<li>示例</li>
|
||
</ul>
|
||
<pre class="hljs"><code>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 class="list">
|
||
<li>启动代理服务器</li>
|
||
<li>示例</li>
|
||
</ul>
|
||
<pre class="hljs"><code>proxy.start();</code></pre></li>
|
||
<li><p>Method: <code>close</code></p>
|
||
<ul class="list">
|
||
<li>关闭代理服务器</li>
|
||
<li>示例</li>
|
||
</ul>
|
||
<pre class="hljs"><code>proxy.close();</code></pre></li>
|
||
</ul>
|
||
</li>
|
||
<li><p>AnyProxy.utils.systemProxyMgr</p>
|
||
<ul class="list">
|
||
<li>管理系统的全局代理配置,方法调用时可能会弹出密码框</li>
|
||
<li>使用示例</li>
|
||
</ul>
|
||
<pre class="hljs"><code><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 class="list">
|
||
<li>管理AnyProxy的证书</li>
|
||
<li><code>AnyProxy.utils.certMgr.ifRootCAFileExists()</code><ul class="list">
|
||
<li>校验系统内是否存在AnyProxy的根证书</li>
|
||
</ul>
|
||
</li>
|
||
<li><code>AnyProxy.utils.certMgr.generateRootCA(callback)</code><ul class="list">
|
||
<li>生成AnyProxy的rootCA,完成后请引导用户信任.crt文件</li>
|
||
</ul>
|
||
</li>
|
||
<li>样例</li>
|
||
</ul>
|
||
<pre class="hljs"><code> <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(<span class="hljs-function">(<span class="hljs-params">error, keyPath</span>) =></span> {
|
||
<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>, { <span class="hljs-attr">cwd</span>: certDir });
|
||
} <span class="hljs-keyword">else</span> {
|
||
exec(<span class="hljs-string">'open .'</span>, { <span class="hljs-attr">cwd</span>: 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>
|
||
<h2 id="关于anyproxy"><a class="header-link" href="#关于anyproxy"></a>关于AnyProxy</h2>
|
||
<ul class="list">
|
||
<li>AnyProxy是支付宝前端团队推出的开源产品</li>
|
||
<li>Change Log: <a href="https://github.com/alibaba/anyproxy/blob/master/CHANGELOG">https://github.com/alibaba/anyproxy/blob/master/CHANGELOG</a></li>
|
||
<li>代码库:<a href="https://github.com/alibaba/anyproxy">https://github.com/alibaba/anyproxy</a></li>
|
||
<li>issue反馈:<a href="https://github.com/alibaba/anyproxy/issues">https://github.com/alibaba/anyproxy/issues</a></li>
|
||
</ul>
|
||
<h2 id="配置帮助"><a class="header-link" href="#配置帮助"></a>配置帮助</h2>
|
||
<h3 id="osx系统信任ca证书"><a class="header-link" href="#osx系统信任ca证书"></a>OSX系统信任CA证书</h3>
|
||
<ul class="list">
|
||
<li>类似这种报错都是因为系统没有信任AnyProxy生成的CA所造成的</li>
|
||
</ul>
|
||
<p class="img-container"><img src="https://zos.alipayobjects.com/rmsportal/CBkLGYgvoHAYwNVAYkpk.png" width="450" /></p>
|
||
<blockquote>
|
||
<p>警告:CA证书和系统安全息息相关,建议亲自生成,并妥善保管</p>
|
||
</blockquote>
|
||
<p>安装CA:</p>
|
||
<ul class="list">
|
||
<li><p>双击打开rootCA.crt</p>
|
||
</li>
|
||
<li><p>确认将证书添加到login或system</p>
|
||
</li>
|
||
</ul>
|
||
<p class="img-container"><img src="https://zos.alipayobjects.com/rmsportal/bCwNUFFpvsmVuljQKrIk.png" width="350" /></p>
|
||
<ul class="list">
|
||
<li>找到刚刚导入的AnyProxy证书,配置为信任(Always Trust)</li>
|
||
</ul>
|
||
<p class="img-container"><img src="https://zos.alipayobjects.com/rmsportal/HOmEElNGdoZEWFMLsTNT.png" width="700" /></p>
|
||
<h3 id="windows系统信任ca证书"><a class="header-link" href="#windows系统信任ca证书"></a>Windows系统信任CA证书</h3>
|
||
<p class="img-container"><img src="https://t.alipayobjects.com/tfscom/T1D3hfXeFtXXXXXXXX.jpg" width="700" /></p>
|
||
<h3 id="配置osx系统代理"><a class="header-link" href="#配置osx系统代理"></a>配置OSX系统代理</h3>
|
||
<ul class="list">
|
||
<li>在wifi高级设置中,配置http代理即可</li>
|
||
</ul>
|
||
<p class="img-container"><img src="https://zos.alipayobjects.com/rmsportal/vduwhobSTypTfgniBvoa.png" width="500" /></p>
|
||
<h3 id="配置浏览器http代理"><a class="header-link" href="#配置浏览器http代理"></a>配置浏览器HTTP代理</h3>
|
||
<ul class="list">
|
||
<li>以Chrome的<a href="https://chrome.google.com/webstore/detail/padekgcemlokbadohgkifijomclgjgif">SwitchyOmega插件</a>为例</li>
|
||
</ul>
|
||
<p class="img-container"><img src="https://zos.alipayobjects.com/rmsportal/jIPZrKmqXRaSledQeJUJ.png" width="500" /></p>
|
||
<h3 id="配置ios/android系统代理"><a class="header-link" href="#配置ios/android系统代理"></a>配置iOS/Android系统代理</h3>
|
||
<ul class="list">
|
||
<li><p>代理服务器都在wifi设置中配置</p>
|
||
</li>
|
||
<li><p>iOS HTTP代理配置</p>
|
||
</li>
|
||
</ul>
|
||
<p class="img-container"><img src="https://zos.alipayobjects.com/rmsportal/tLGqIozhffTccUgPakuw.png" width="260" /></p>
|
||
<ul class="list">
|
||
<li>Android HTTP代理配置</li>
|
||
</ul>
|
||
<p class="img-container"><img src="https://zos.alipayobjects.com/rmsportal/YQtbQYVNuOszZGdAOauU.png" width="260" /></p>
|
||
</div>
|
||
</article>
|
||
|
||
<script src="//cdn.bootcss.com/zepto/1.2.0/zepto.min.js"></script>
|
||
<script>
|
||
window.onload = function(){
|
||
var itemList = [];
|
||
var targetMap = {};
|
||
$("[id]", ".main-content").map(function (index, heading) {
|
||
targetMap[heading.getAttribute('id')] = heading;
|
||
});
|
||
|
||
$("#j_toc li").map(function (index, item) {
|
||
if (item.className.indexOf('sidebar-header-2') >= 0 || item.className.indexOf('sidebar-header-3') >= 0) {
|
||
var targetName = item.firstChild.getAttribute('href').replace('#', '');
|
||
var targetItem = targetMap[targetName];
|
||
itemList.push({ target: targetItem, tocItem: item, top: $(targetItem).position().top });
|
||
}
|
||
});
|
||
|
||
var updateTocActive = function (e) {
|
||
var windowHeight = window.innerHeight;
|
||
//find the first item to match
|
||
var scrollYThres = window.scrollY + 200;
|
||
var target;
|
||
if (scrollYThres < 100) {
|
||
target = itemList[0].tocItem;
|
||
} else {
|
||
itemList.forEach(function (item, index) {
|
||
if (target) return;
|
||
if (index > 0) {
|
||
if (item.top >= scrollYThres) {
|
||
target = itemList[index - 1].tocItem;
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
$('.toc-active').removeClass('toc-active');
|
||
$(target).addClass('toc-active');
|
||
};
|
||
|
||
window.onscroll = updateTocActive;
|
||
updateTocActive();
|
||
}
|
||
</script>
|
||
</body>
|
||
|
||
</html> |