mirror of
https://github.com/alibaba/anyproxy.git
synced 2025-05-10 06:48:26 +00:00
add document for 4.x
This commit is contained in:
parent
a39272cdfb
commit
19ad4d54a6
BIN
.DS_Store
vendored
BIN
.DS_Store
vendored
Binary file not shown.
96
4.x/assets/css/atom-one-light.css
Normal file
96
4.x/assets/css/atom-one-light.css
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
|
||||
Atom One Light by Daniel Gamage
|
||||
Original One Light Syntax theme from https://github.com/atom/one-light-syntax
|
||||
|
||||
base: #fafafa
|
||||
mono-1: #383a42
|
||||
mono-2: #686b77
|
||||
mono-3: #a0a1a7
|
||||
hue-1: #0184bb
|
||||
hue-2: #4078f2
|
||||
hue-3: #a626a4
|
||||
hue-4: #50a14f
|
||||
hue-5: #e45649
|
||||
hue-5-2: #c91243
|
||||
hue-6: #986801
|
||||
hue-6-2: #c18401
|
||||
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
color: #383a42;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #a0a1a7;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-doctag,
|
||||
.hljs-keyword,
|
||||
.hljs-formula {
|
||||
color: #a626a4;
|
||||
}
|
||||
|
||||
.hljs-section,
|
||||
.hljs-name,
|
||||
.hljs-selector-tag,
|
||||
.hljs-deletion,
|
||||
.hljs-subst {
|
||||
color: #e45649;
|
||||
}
|
||||
|
||||
.hljs-literal {
|
||||
color: #0184bb;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-regexp,
|
||||
.hljs-addition,
|
||||
.hljs-attribute,
|
||||
.hljs-meta-string {
|
||||
color: #50a14f;
|
||||
}
|
||||
|
||||
.hljs-built_in,
|
||||
.hljs-class .hljs-title {
|
||||
color: #c18401;
|
||||
}
|
||||
|
||||
.hljs-attr,
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-type,
|
||||
.hljs-selector-class,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo,
|
||||
.hljs-number {
|
||||
color: #986801;
|
||||
}
|
||||
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-link,
|
||||
.hljs-meta,
|
||||
.hljs-selector-id,
|
||||
.hljs-title {
|
||||
color: #4078f2;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-link {
|
||||
text-decoration: underline;
|
||||
}
|
56
4.x/assets/css/custom.css
Normal file
56
4.x/assets/css/custom.css
Normal file
@ -0,0 +1,56 @@
|
||||
body{
|
||||
max-width: 980px;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.main-content{
|
||||
padding-left: 200px;
|
||||
width: 980px;
|
||||
}
|
||||
|
||||
.markdown-body blockquote{
|
||||
border-left: 4px solid #F9CC9D;
|
||||
}
|
||||
|
||||
.markdown-body .img-container{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (min-width: 43.75em) {
|
||||
body {
|
||||
padding: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.markdown-body{
|
||||
display: flex;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.toc-container{
|
||||
width: 200px;
|
||||
position: fixed;
|
||||
top: 42px;
|
||||
}
|
||||
|
||||
.toc-container ul{
|
||||
font-size: 12px;
|
||||
list-style: none;
|
||||
padding-left: 15px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.toc-container a{
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.toc-active a{
|
||||
opacity: 1;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sidebar-header-1 { display: none }
|
||||
.sidebar-header-2 { margin-left: 0px; }
|
||||
.sidebar-header-3 { margin-left: 15px; }
|
||||
.sidebar-header-4 { display: none }
|
||||
.sidebar-header-5 { display: none }
|
709
4.x/assets/css/github-markdown.css
Normal file
709
4.x/assets/css/github-markdown.css
Normal file
@ -0,0 +1,709 @@
|
||||
@font-face {
|
||||
font-family: octicons-anchor;
|
||||
src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAYcAA0AAAAACjQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABMAAAABwAAAAca8vGTk9TLzIAAAFMAAAARAAAAFZG1VHVY21hcAAAAZAAAAA+AAABQgAP9AdjdnQgAAAB0AAAAAQAAAAEACICiGdhc3AAAAHUAAAACAAAAAj//wADZ2x5ZgAAAdwAAADRAAABEKyikaNoZWFkAAACsAAAAC0AAAA2AtXoA2hoZWEAAALgAAAAHAAAACQHngNFaG10eAAAAvwAAAAQAAAAEAwAACJsb2NhAAADDAAAAAoAAAAKALIAVG1heHAAAAMYAAAAHwAAACABEAB2bmFtZQAAAzgAAALBAAAFu3I9x/Nwb3N0AAAF/AAAAB0AAAAvaoFvbwAAAAEAAAAAzBdyYwAAAADP2IQvAAAAAM/bz7t4nGNgZGFgnMDAysDB1Ml0hoGBoR9CM75mMGLkYGBgYmBlZsAKAtJcUxgcPsR8iGF2+O/AEMPsznAYKMwIkgMA5REMOXicY2BgYGaAYBkGRgYQsAHyGMF8FgYFIM0ChED+h5j//yEk/3KoSgZGNgYYk4GRCUgwMaACRoZhDwCs7QgGAAAAIgKIAAAAAf//AAJ4nHWMMQrCQBBF/0zWrCCIKUQsTDCL2EXMohYGSSmorScInsRGL2DOYJe0Ntp7BK+gJ1BxF1stZvjz/v8DRghQzEc4kIgKwiAppcA9LtzKLSkdNhKFY3HF4lK69ExKslx7Xa+vPRVS43G98vG1DnkDMIBUgFN0MDXflU8tbaZOUkXUH0+U27RoRpOIyCKjbMCVejwypzJJG4jIwb43rfl6wbwanocrJm9XFYfskuVC5K/TPyczNU7b84CXcbxks1Un6H6tLH9vf2LRnn8Ax7A5WQAAAHicY2BkYGAA4teL1+yI57f5ysDNwgAC529f0kOmWRiYVgEpDgYmEA8AUzEKsQAAAHicY2BkYGB2+O/AEMPCAAJAkpEBFbAAADgKAe0EAAAiAAAAAAQAAAAEAAAAAAAAKgAqACoAiAAAeJxjYGRgYGBhsGFgYgABEMkFhAwM/xn0QAIAD6YBhwB4nI1Ty07cMBS9QwKlQapQW3VXySvEqDCZGbGaHULiIQ1FKgjWMxknMfLEke2A+IJu+wntrt/QbVf9gG75jK577Lg8K1qQPCfnnnt8fX1NRC/pmjrk/zprC+8D7tBy9DHgBXoWfQ44Av8t4Bj4Z8CLtBL9CniJluPXASf0Lm4CXqFX8Q84dOLnMB17N4c7tBo1AS/Qi+hTwBH4rwHHwN8DXqQ30XXAS7QaLwSc0Gn8NuAVWou/gFmnjLrEaEh9GmDdDGgL3B4JsrRPDU2hTOiMSuJUIdKQQayiAth69r6akSSFqIJuA19TrzCIaY8sIoxyrNIrL//pw7A2iMygkX5vDj+G+kuoLdX4GlGK/8Lnlz6/h9MpmoO9rafrz7ILXEHHaAx95s9lsI7AHNMBWEZHULnfAXwG9/ZqdzLI08iuwRloXE8kfhXYAvE23+23DU3t626rbs8/8adv+9DWknsHp3E17oCf+Z48rvEQNZ78paYM38qfk3v/u3l3u3GXN2Dmvmvpf1Srwk3pB/VSsp512bA/GG5i2WJ7wu430yQ5K3nFGiOqgtmSB5pJVSizwaacmUZzZhXLlZTq8qGGFY2YcSkqbth6aW1tRmlaCFs2016m5qn36SbJrqosG4uMV4aP2PHBmB3tjtmgN2izkGQyLWprekbIntJFing32a5rKWCN/SdSoga45EJykyQ7asZvHQ8PTm6cslIpwyeyjbVltNikc2HTR7YKh9LBl9DADC0U/jLcBZDKrMhUBfQBvXRzLtFtjU9eNHKin0x5InTqb8lNpfKv1s1xHzTXRqgKzek/mb7nB8RZTCDhGEX3kK/8Q75AmUM/eLkfA+0Hi908Kx4eNsMgudg5GLdRD7a84npi+YxNr5i5KIbW5izXas7cHXIMAau1OueZhfj+cOcP3P8MNIWLyYOBuxL6DRylJ4cAAAB4nGNgYoAALjDJyIAOWMCiTIxMLDmZedkABtIBygAAAA==) format('woff');
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: white;
|
||||
max-width: 790px;
|
||||
margin: 0 auto;
|
||||
padding: 30px 0;
|
||||
}
|
||||
|
||||
.markdown-body {
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
color: #333;
|
||||
overflow: hidden;
|
||||
font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.markdown-body a {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.markdown-body a:active,
|
||||
.markdown-body a:hover {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.markdown-body strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.markdown-body h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
.markdown-body img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.markdown-body hr {
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.markdown-body pre {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.markdown-body code,
|
||||
.markdown-body kbd,
|
||||
.markdown-body pre {
|
||||
font-family: monospace, monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.markdown-body input {
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.markdown-body html input[disabled] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.markdown-body input {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.markdown-body input[type="checkbox"] {
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.markdown-body table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
.markdown-body td,
|
||||
.markdown-body th {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.markdown-body * {
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.markdown-body input {
|
||||
font: 13px/1.4 Helvetica, arial, freesans, clean, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
}
|
||||
|
||||
.markdown-body a {
|
||||
color: #4183c4;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.markdown-body a:hover,
|
||||
.markdown-body a:focus,
|
||||
.markdown-body a:active {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.markdown-body hr {
|
||||
height: 0;
|
||||
margin: 15px 0;
|
||||
overflow: hidden;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.markdown-body hr:before {
|
||||
display: table;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.markdown-body hr:after {
|
||||
display: table;
|
||||
clear: both;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.markdown-body h1,
|
||||
.markdown-body h2,
|
||||
.markdown-body h3,
|
||||
.markdown-body h4,
|
||||
.markdown-body h5,
|
||||
.markdown-body h6 {
|
||||
margin-top: 15px;
|
||||
margin-bottom: 15px;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.markdown-body h1 {
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
.markdown-body h2 {
|
||||
font-size: 21px;
|
||||
}
|
||||
|
||||
.markdown-body h3 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.markdown-body h4 {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.markdown-body h5 {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.markdown-body h6 {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.markdown-body blockquote {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.markdown-body ul,
|
||||
.markdown-body ol {
|
||||
padding: 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.markdown-body ol ol,
|
||||
.markdown-body ul ol {
|
||||
list-style-type: lower-roman;
|
||||
}
|
||||
|
||||
.markdown-body ul ul ol,
|
||||
.markdown-body ul ol ol,
|
||||
.markdown-body ol ul ol,
|
||||
.markdown-body ol ol ol {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
|
||||
.markdown-body dd {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.markdown-body code {
|
||||
font: 12px Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
}
|
||||
|
||||
.markdown-body pre {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
font: 12px Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
}
|
||||
|
||||
.markdown-body kbd {
|
||||
background-color: #e7e7e7;
|
||||
background-image: -webkit-linear-gradient(#fefefe, #e7e7e7);
|
||||
background-image: linear-gradient(#fefefe, #e7e7e7);
|
||||
background-repeat: repeat-x;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #cfcfcf;
|
||||
color: #000;
|
||||
padding: 3px 5px;
|
||||
line-height: 10px;
|
||||
font: 11px Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.markdown-body>*:first-child {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.markdown-body>*:last-child {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.markdown-body .anchor {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
padding-right: 6px;
|
||||
padding-left: 30px;
|
||||
margin-left: -30px;
|
||||
}
|
||||
|
||||
.markdown-body .anchor:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.markdown-body h1,
|
||||
.markdown-body h2,
|
||||
.markdown-body h3,
|
||||
.markdown-body h4,
|
||||
.markdown-body h5,
|
||||
.markdown-body h6 {
|
||||
position: relative;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 16px;
|
||||
font-weight: bold;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.markdown-body h1 .octicon-link,
|
||||
.markdown-body h2 .octicon-link,
|
||||
.markdown-body h3 .octicon-link,
|
||||
.markdown-body h4 .octicon-link,
|
||||
.markdown-body h5 .octicon-link,
|
||||
.markdown-body h6 .octicon-link {
|
||||
display: none;
|
||||
color: #000;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.markdown-body h1:hover .anchor,
|
||||
.markdown-body h2:hover .anchor,
|
||||
.markdown-body h3:hover .anchor,
|
||||
.markdown-body h4:hover .anchor,
|
||||
.markdown-body h5:hover .anchor,
|
||||
.markdown-body h6:hover .anchor {
|
||||
height: 1em;
|
||||
padding-left: 8px;
|
||||
margin-left: -30px;
|
||||
line-height: 1;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.markdown-body h1:hover .anchor .octicon-link,
|
||||
.markdown-body h2:hover .anchor .octicon-link,
|
||||
.markdown-body h3:hover .anchor .octicon-link,
|
||||
.markdown-body h4:hover .anchor .octicon-link,
|
||||
.markdown-body h5:hover .anchor .octicon-link,
|
||||
.markdown-body h6:hover .anchor .octicon-link {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.markdown-body h1 {
|
||||
padding-bottom: 0.3em;
|
||||
font-size: 2.25em;
|
||||
line-height: 1.2;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.markdown-body h2 {
|
||||
padding-bottom: 0.3em;
|
||||
font-size: 1.75em;
|
||||
line-height: 1.225;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.markdown-body h3 {
|
||||
font-size: 1.5em;
|
||||
line-height: 1.43;
|
||||
}
|
||||
|
||||
.markdown-body h4 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
.markdown-body h5 {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.markdown-body h6 {
|
||||
font-size: 1em;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.markdown-body p,
|
||||
.markdown-body blockquote,
|
||||
.markdown-body ul,
|
||||
.markdown-body ol,
|
||||
.markdown-body dl,
|
||||
.markdown-body table,
|
||||
.markdown-body pre {
|
||||
margin-top: 0;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.markdown-body hr {
|
||||
height: 4px;
|
||||
padding: 0;
|
||||
margin: 16px 0;
|
||||
background-color: #e7e7e7;
|
||||
border: 0 none;
|
||||
}
|
||||
|
||||
.markdown-body ul,
|
||||
.markdown-body ol {
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
.markdown-body ul ul,
|
||||
.markdown-body ul ol,
|
||||
.markdown-body ol ol,
|
||||
.markdown-body ol ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.markdown-body li>p {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.markdown-body dl {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.markdown-body dl dt {
|
||||
padding: 0;
|
||||
margin-top: 16px;
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.markdown-body dl dd {
|
||||
padding: 0 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.markdown-body blockquote {
|
||||
padding: 0 15px;
|
||||
color: #777;
|
||||
border-left: 4px solid #ddd;
|
||||
}
|
||||
|
||||
.markdown-body blockquote>:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.markdown-body blockquote>:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.markdown-body table {
|
||||
display: block;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
word-break: normal;
|
||||
word-break: keep-all;
|
||||
}
|
||||
|
||||
.markdown-body table th {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.markdown-body table th,
|
||||
.markdown-body table td {
|
||||
padding: 6px 13px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.markdown-body table tr {
|
||||
background-color: #fff;
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.markdown-body table tr:nth-child(2n) {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
.markdown-body img {
|
||||
max-width: 100%;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.markdown-body code {
|
||||
padding: 0;
|
||||
padding-top: 0.2em;
|
||||
padding-bottom: 0.2em;
|
||||
margin: 0;
|
||||
font-size: 85%;
|
||||
background-color: rgba(0,0,0,0.04);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.markdown-body code:before,
|
||||
.markdown-body code:after {
|
||||
letter-spacing: -0.2em;
|
||||
content: "\00a0";
|
||||
}
|
||||
|
||||
.markdown-body pre>code {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-size: 100%;
|
||||
word-break: normal;
|
||||
white-space: pre;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.markdown-body .highlight {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.markdown-body .highlight pre,
|
||||
.markdown-body pre {
|
||||
padding: 16px;
|
||||
overflow: auto;
|
||||
font-size: 85%;
|
||||
line-height: 1.45;
|
||||
background-color: #f7f7f7;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.markdown-body .highlight pre {
|
||||
margin-bottom: 0;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
.markdown-body pre {
|
||||
word-wrap: normal;
|
||||
}
|
||||
|
||||
.markdown-body pre code {
|
||||
display: inline;
|
||||
max-width: initial;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: initial;
|
||||
line-height: inherit;
|
||||
word-wrap: normal;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.markdown-body pre code:before,
|
||||
.markdown-body pre code:after {
|
||||
content: normal;
|
||||
}
|
||||
|
||||
.markdown-body .highlight {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .mf,
|
||||
.markdown-body .highlight .mh,
|
||||
.markdown-body .highlight .mi,
|
||||
.markdown-body .highlight .mo,
|
||||
.markdown-body .highlight .il,
|
||||
.markdown-body .highlight .m {
|
||||
color: #945277;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .s,
|
||||
.markdown-body .highlight .sb,
|
||||
.markdown-body .highlight .sc,
|
||||
.markdown-body .highlight .sd,
|
||||
.markdown-body .highlight .s2,
|
||||
.markdown-body .highlight .se,
|
||||
.markdown-body .highlight .sh,
|
||||
.markdown-body .highlight .si,
|
||||
.markdown-body .highlight .sx,
|
||||
.markdown-body .highlight .s1 {
|
||||
color: #df5000;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .kc,
|
||||
.markdown-body .highlight .kd,
|
||||
.markdown-body .highlight .kn,
|
||||
.markdown-body .highlight .kp,
|
||||
.markdown-body .highlight .kr,
|
||||
.markdown-body .highlight .kt,
|
||||
.markdown-body .highlight .k,
|
||||
.markdown-body .highlight .o {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .kt {
|
||||
color: #458;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .c,
|
||||
.markdown-body .highlight .cm,
|
||||
.markdown-body .highlight .c1 {
|
||||
color: #998;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .cp,
|
||||
.markdown-body .highlight .cs {
|
||||
color: #999;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .cs {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .n {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .na,
|
||||
.markdown-body .highlight .nv,
|
||||
.markdown-body .highlight .vc,
|
||||
.markdown-body .highlight .vg,
|
||||
.markdown-body .highlight .vi {
|
||||
color: #008080;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .nb {
|
||||
color: #0086B3;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .nc {
|
||||
color: #458;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .no {
|
||||
color: #094e99;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .ni {
|
||||
color: #800080;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .ne {
|
||||
color: #990000;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .nf {
|
||||
color: #945277;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .nn {
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .nt {
|
||||
color: #000080;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .err {
|
||||
color: #a61717;
|
||||
background-color: #e3d2d2;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .gd {
|
||||
color: #000;
|
||||
background-color: #fdd;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .gd .x {
|
||||
color: #000;
|
||||
background-color: #faa;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .ge {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .gr {
|
||||
color: #aa0000;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .gh {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .gi {
|
||||
color: #000;
|
||||
background-color: #dfd;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .gi .x {
|
||||
color: #000;
|
||||
background-color: #afa;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .go {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .gp {
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .gs {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .gu {
|
||||
color: #800080;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .gt {
|
||||
color: #aa0000;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .ow {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .w {
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .sr {
|
||||
color: #017936;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .ss {
|
||||
color: #8b467f;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .bp {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.markdown-body .highlight .gc {
|
||||
color: #999;
|
||||
background-color: #EAF2F5;
|
||||
}
|
||||
|
||||
.markdown-body .octicon {
|
||||
font: normal normal 16px octicons-anchor;
|
||||
line-height: 1;
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.markdown-body .octicon-link:before {
|
||||
content: '\f05c';
|
||||
}
|
||||
|
||||
.markdown-body .task-list-item {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.markdown-body .task-list-item+.task-list-item {
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.markdown-body .task-list-item input {
|
||||
float: left;
|
||||
margin: 0.3em 0 0.25em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
@media (min-width: 43.75em) {
|
||||
body {
|
||||
padding: 30px;
|
||||
}
|
||||
}
|
96
4.x/assets/css/hljs-github.min.css
vendored
Normal file
96
4.x/assets/css/hljs-github.min.css
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
|
||||
Atom One Light by Daniel Gamage
|
||||
Original One Light Syntax theme from https://github.com/atom/one-light-syntax
|
||||
|
||||
base: #fafafa
|
||||
mono-1: #383a42
|
||||
mono-2: #686b77
|
||||
mono-3: #a0a1a7
|
||||
hue-1: #0184bb
|
||||
hue-2: #4078f2
|
||||
hue-3: #a626a4
|
||||
hue-4: #50a14f
|
||||
hue-5: #e45649
|
||||
hue-5-2: #c91243
|
||||
hue-6: #986801
|
||||
hue-6-2: #c18401
|
||||
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
color: #383a42;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #a0a1a7;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-doctag,
|
||||
.hljs-keyword,
|
||||
.hljs-formula {
|
||||
color: #a626a4;
|
||||
}
|
||||
|
||||
.hljs-section,
|
||||
.hljs-name,
|
||||
.hljs-selector-tag,
|
||||
.hljs-deletion,
|
||||
.hljs-subst {
|
||||
color: #e45649;
|
||||
}
|
||||
|
||||
.hljs-literal {
|
||||
color: #0184bb;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-regexp,
|
||||
.hljs-addition,
|
||||
.hljs-attribute,
|
||||
.hljs-meta-string {
|
||||
color: #50a14f;
|
||||
}
|
||||
|
||||
.hljs-built_in,
|
||||
.hljs-class .hljs-title {
|
||||
color: #c18401;
|
||||
}
|
||||
|
||||
.hljs-attr,
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-type,
|
||||
.hljs-selector-class,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo,
|
||||
.hljs-number {
|
||||
color: #986801;
|
||||
}
|
||||
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-link,
|
||||
.hljs-meta,
|
||||
.hljs-selector-id,
|
||||
.hljs-title {
|
||||
color: #4078f2;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-link {
|
||||
text-decoration: underline;
|
||||
}
|
47
4.x/assets/css/pilcrow.css
Normal file
47
4.x/assets/css/pilcrow.css
Normal file
@ -0,0 +1,47 @@
|
||||
/* needed because the container has overflow: hidden, but the pilcrows overflow */
|
||||
.markdown-body {
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.markdown-body h1,
|
||||
.markdown-body h2,
|
||||
.markdown-body h3,
|
||||
.markdown-body h4,
|
||||
.markdown-body h5,
|
||||
.markdown-body h6 {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.markdown-body h1:hover .header-link:before,
|
||||
.markdown-body h2:hover .header-link:before,
|
||||
.markdown-body h3:hover .header-link:before,
|
||||
.markdown-body h4:hover .header-link:before,
|
||||
.markdown-body h5:hover .header-link:before,
|
||||
.markdown-body h6:hover .header-link:before {
|
||||
content: "\00B6";/* pilcrow */
|
||||
color: #888;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.markdown-body .header-link {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -0.7em;
|
||||
display: block;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
.markdown-body h1:hover .header-link,
|
||||
.markdown-body h2:hover .header-link,
|
||||
.markdown-body h3:hover .header-link,
|
||||
.markdown-body h4:hover .header-link,
|
||||
.markdown-body h5:hover .header-link,
|
||||
.markdown-body h6:hover .header-link {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
}
|
756
4.x/index.html
Normal file
756
4.x/index.html
Normal file
@ -0,0 +1,756 @@
|
||||
<!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
|
||||
start proyx:
|
||||
anyproxy --rule sample_use_local_response.js
|
||||
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
|
||||
start proyx:
|
||||
anyproxy --rule sample_modify_request_header.js
|
||||
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
|
||||
start proyx:
|
||||
anyproxy --rule sample_modify_request_data.js
|
||||
test:
|
||||
curl http://httpbin.org/ --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'</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/">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
|
||||
start proyx:
|
||||
anyproxy --rule sample_modify_request_path.js
|
||||
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
|
||||
start proyx:
|
||||
anyproxy --rule sample_modify_request_protocol.js
|
||||
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
|
||||
start proyx:
|
||||
anyproxy --rule sample_modify_response_statuscode.js
|
||||
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
|
||||
start proyx:
|
||||
anyproxy --rule sample_modify_response_header.js
|
||||
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
|
||||
start proyx:
|
||||
anyproxy --rule sample.js
|
||||
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>
|
||||
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 scrollY = window.scrollY;
|
||||
var target;
|
||||
if (scrollY < 100) {
|
||||
target = itemList[0].tocItem;
|
||||
} else {
|
||||
itemList.forEach(function (item, index) {
|
||||
if (target) return;
|
||||
|
||||
if (index < itemList.length - 1) {
|
||||
if (item.top <= scrollY + windowHeight / 2 && itemList[index + 1].top > scrollY + windowHeight / 2) {
|
||||
target = item.tocItem;
|
||||
}
|
||||
} else {
|
||||
target = item.tocItem;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$('.toc-active').removeClass('toc-active');
|
||||
$(target).addClass('toc-active');
|
||||
};
|
||||
|
||||
window.onscroll = updateTocActive;
|
||||
updateTocActive();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -30,7 +30,7 @@
|
||||
<div class="logo">
|
||||
<img src="http://gtms04.alicdn.com/tps/i4/TB1XfxDHpXXXXXpapXX20ySQVXX-512-512.png" width="250" height="250" alt="anyproxy logo" />
|
||||
</div>
|
||||
<h2 class="slogan">AnyProxy是一个开放式的HTTP/HTTPS代理,你可以灵活控制各种网络数据</h2>
|
||||
<h2 class="slogan">AnyProxy 4.x版正在Beta中,欢迎试用 Ref:<a href="/4.x/">AnyProxy 4.x 文档</a></h2>
|
||||
<div class="action">
|
||||
<iframe src="https://ghbtns.com/github-btn.html?user=alibaba&repo=anyproxy&type=star&count=true" frameborder="0" scrolling="0" width="100px" height="20px"></iframe>
|
||||
<iframe src="https://ghbtns.com/github-btn.html?user=alibaba&repo=anyproxy&type=fork&count=true" frameborder="0" scrolling="0" width="100px" height="20px"></iframe>
|
||||
|
@ -23,7 +23,7 @@ body {
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
color: #5a5a5a;
|
||||
color: #5A5A5A;
|
||||
}
|
||||
.wrapper .cornerBtnWrapper a {
|
||||
display: inline-block;
|
||||
@ -36,7 +36,7 @@ body {
|
||||
}
|
||||
.wrapper a {
|
||||
font-size: 16px;
|
||||
color: #00aaee;
|
||||
color: #00AAEE;
|
||||
}
|
||||
.wrapper h4.subTitle {
|
||||
font-size: 30px;
|
||||
@ -44,7 +44,7 @@ body {
|
||||
padding: 50px 0 10px 0;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
color: #5a5a5a;
|
||||
color: #5A5A5A;
|
||||
}
|
||||
.wrapper h4.subTitle.white {
|
||||
color: #FFF;
|
||||
@ -57,12 +57,12 @@ body {
|
||||
border: 1px solid #FFF;
|
||||
}
|
||||
.wrapper .actionBtn.actionBtnWhite:hover {
|
||||
background: #f9f9f9;
|
||||
color: #326eeb;
|
||||
background: #F9F9F9;
|
||||
color: #326EEB;
|
||||
}
|
||||
.wrapper .actionBtn {
|
||||
color: #326eeb;
|
||||
border: 1px solid #326eeb;
|
||||
color: #326EEB;
|
||||
border: 1px solid #326EEB;
|
||||
line-height: 30px;
|
||||
font-size: 30px;
|
||||
padding: 20px 45px;
|
||||
@ -77,8 +77,8 @@ body {
|
||||
}
|
||||
}
|
||||
.wrapper .actionBtn:hover {
|
||||
background: #326eeb;
|
||||
color: #f9f9f9;
|
||||
background: #326EEB;
|
||||
color: #F9F9F9;
|
||||
}
|
||||
.wrapper > div {
|
||||
width: 100%;
|
||||
@ -103,11 +103,11 @@ body {
|
||||
}
|
||||
.brief .slogan {
|
||||
font-size: 16px;
|
||||
color: #5a5a5a;
|
||||
color: #5A5A5A;
|
||||
padding: 0 20px;
|
||||
}
|
||||
.feature {
|
||||
background: #dedede;
|
||||
background: #DEDEDE;
|
||||
}
|
||||
.feature .featureContent {
|
||||
width: 1200px;
|
||||
@ -135,18 +135,18 @@ body {
|
||||
width: 70px;
|
||||
text-align: center;
|
||||
font-size: 40px;
|
||||
color: #5a5a5a;
|
||||
color: #5A5A5A;
|
||||
}
|
||||
.feature .featureContent .iconWrapper .bigger {
|
||||
font-size: 44px;
|
||||
}
|
||||
.feature .featureContent h4 {
|
||||
color: #5a5a5a;
|
||||
color: #5A5A5A;
|
||||
margin: 12px auto 2px;
|
||||
font-size: 20px;
|
||||
}
|
||||
.feature .featureContent h5 {
|
||||
color: #777777;
|
||||
color: #777;
|
||||
margin: 0;
|
||||
}
|
||||
.feature .featureContent h5,
|
||||
@ -174,7 +174,7 @@ body {
|
||||
}
|
||||
}
|
||||
.quickstart {
|
||||
background: #f9f9f9;
|
||||
background: #F9F9F9;
|
||||
}
|
||||
.quickstart .quickstartContent {
|
||||
position: relative;
|
||||
@ -213,12 +213,12 @@ body {
|
||||
}
|
||||
}
|
||||
.listSection li {
|
||||
color: #5a5a5a;
|
||||
color: #5A5A5A;
|
||||
font-size: 16px;
|
||||
line-height: 40px;
|
||||
}
|
||||
.sample {
|
||||
background: #f9f9f9;
|
||||
background: #F9F9F9;
|
||||
}
|
||||
.sample .sampleContent {
|
||||
width: 890px;
|
||||
@ -235,7 +235,7 @@ body {
|
||||
.sample .itemTitle {
|
||||
font-size: 16px;
|
||||
margin: 0px 10px;
|
||||
color: #5a5a5a;
|
||||
color: #5A5A5A;
|
||||
}
|
||||
@media only screen and (min-device-width: 320px) and (max-device-width: 600px) and (-webkit-min-device-pixel-ratio: 2) {
|
||||
.sample .itemTitle {
|
||||
@ -275,7 +275,7 @@ body {
|
||||
}
|
||||
.sample hr {
|
||||
border: none;
|
||||
border-top: 1px solid #777777;
|
||||
border-top: 1px solid #777;
|
||||
width: 80%;
|
||||
margin: 0 auto;
|
||||
padding: 15px 0;
|
||||
@ -285,11 +285,11 @@ body {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
.readMore {
|
||||
background: #f9f9f9;
|
||||
background: #F9F9F9;
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
.learnMore {
|
||||
background: #326eeb;
|
||||
background: #326EEB;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
padding: 120px 0;
|
||||
|
@ -44,7 +44,7 @@
|
||||
<i class="iconfont"></i>
|
||||
</span>
|
||||
<h4>Based on Node.js</h4>
|
||||
<h5>It's all javascript and easy to learn.</h5>
|
||||
<h5>It's all javascript and easy to learn.</h5>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="iconWrapper">
|
||||
|
@ -44,7 +44,7 @@
|
||||
<i class="iconfont"></i>
|
||||
</span>
|
||||
<h4>Based on Node.js</h4>
|
||||
<h5>It's all javascript and easy to learn.</h5>
|
||||
<h5>It's all javascript and easy to learn.</h5>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="iconWrapper">
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"cn":{
|
||||
"language":"cn",
|
||||
"summary":"AnyProxy是一个开放式的HTTP/HTTPS代理,你可以灵活控制各种网络数据",
|
||||
"summary":"AnyProxy 4.x版正在Beta中,欢迎试用 Ref:<a href=\"/4.x/\">AnyProxy 4.x 文档</a>",
|
||||
"featureA":"基于Node.js",
|
||||
"featureADesc":"全程JavaScript,学习无压力",
|
||||
"featureB":"支持Https",
|
||||
|
@ -30,7 +30,7 @@
|
||||
<div class="logo">
|
||||
<img src="http://gtms04.alicdn.com/tps/i4/TB1XfxDHpXXXXXpapXX20ySQVXX-512-512.png" width="250" height="250" alt="anyproxy logo" />
|
||||
</div>
|
||||
<h2 class="slogan">${summary}</h2>
|
||||
<h2 class="slogan">$${summary}</h2>
|
||||
<div class="action">
|
||||
<iframe src="https://ghbtns.com/github-btn.html?user=alibaba&repo=anyproxy&type=star&count=true" frameborder="0" scrolling="0" width="100px" height="20px"></iframe>
|
||||
<iframe src="https://ghbtns.com/github-btn.html?user=alibaba&repo=anyproxy&type=fork&count=true" frameborder="0" scrolling="0" width="100px" height="20px"></iframe>
|
||||
|
Loading…
x
Reference in New Issue
Block a user