").append(m.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},m.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){m.fn[b]=function(a){return this.on(b,a)}}),m.expr.filters.animated=function(a){return m.grep(m.timers,function(b){return a===b.elem}).length};var cc=a.document.documentElement;function dc(a){return m.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}m.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=m.css(a,"position"),l=m(a),n={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=m.css(a,"top"),i=m.css(a,"left"),j=("absolute"===k||"fixed"===k)&&m.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),m.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(n.top=b.top-h.top+g),null!=b.left&&(n.left=b.left-h.left+e),"using"in b?b.using.call(a,n):l.css(n)}},m.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){m.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,m.contains(b,e)?(typeof e.getBoundingClientRect!==K&&(d=e.getBoundingClientRect()),c=dc(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===m.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),m.nodeName(a[0],"html")||(c=a.offset()),c.top+=m.css(a[0],"borderTopWidth",!0),c.left+=m.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-m.css(d,"marginTop",!0),left:b.left-c.left-m.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||cc;while(a&&!m.nodeName(a,"html")&&"static"===m.css(a,"position"))a=a.offsetParent;return a||cc})}}),m.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);m.fn[a]=function(d){return V(this,function(a,d,e){var f=dc(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?m(f).scrollLeft():e,c?e:m(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),m.each(["top","left"],function(a,b){m.cssHooks[b]=La(k.pixelPosition,function(a,c){return c?(c=Ja(a,b),Ha.test(c)?m(a).position()[b]+"px":c):void 0})}),m.each({Height:"height",Width:"width"},function(a,b){m.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){m.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return V(this,function(b,c,d){var e;return m.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?m.css(b,c,g):m.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),m.fn.size=function(){return this.length},m.fn.andSelf=m.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return m});var ec=a.jQuery,fc=a.$;return m.noConflict=function(b){return a.$===m&&(a.$=fc),b&&a.jQuery===m&&(a.jQuery=ec),m},typeof b===K&&(a.jQuery=a.$=m),m});
6 | //# sourceMappingURL=jquery.min.map
--------------------------------------------------------------------------------
/docs/style/jquery.toTop.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * jQuery.toTop.js v1.1
3 | * Developed by: MMK Jony
4 | * Fork on Github: https://github.com/mmkjony/jQuery.toTop
5 | **/
6 |
7 | !function(o){"use strict";o.fn.toTop=function(t){var i=this,e=o(window),s=o("html, body"),n=o.extend({autohide:!0,offset:420,speed:500,position:!0,right:15,bottom:30},t);i.css({cursor:"pointer"}),n.autohide&&i.css("display","none"),n.position&&i.css({position:"fixed",right:n.right,bottom:n.bottom}),i.click(function(){s.animate({scrollTop:0},n.speed)}),e.scroll(function(){var o=e.scrollTop();n.autohide&&(o>n.offset?i.fadeIn(n.speed):i.fadeOut(n.speed))})}}(jQuery);
8 |
--------------------------------------------------------------------------------
/docs/style/myStyle.css:
--------------------------------------------------------------------------------
1 |
2 | /* 置顶插件 */
3 | .to-top {
4 | display: none;
5 | padding: 10px 20px;
6 | margin-right: 10px;
7 | color: #fff;
8 | border-radius: 10px;
9 | background-color: rgb(66, 185, 131);
10 | }
11 |
--------------------------------------------------------------------------------
/docs/sw.js:
--------------------------------------------------------------------------------
1 | /* ===========================================================
2 | * docsify sw.js
3 | * ===========================================================
4 | * Copyright 2016 @huxpro
5 | * Licensed under Apache 2.0
6 | * Register service worker.
7 | * ========================================================== */
8 |
9 | const RUNTIME = 'docsify'
10 | const HOSTNAME_WHITELIST = [
11 | self.location.hostname,
12 | 'fonts.gstatic.com',
13 | 'fonts.googleapis.com',
14 | 'cdn.jsdelivr.net'
15 | ]
16 |
17 | // The Util Function to hack URLs of intercepted requests
18 | const getFixedUrl = (req) => {
19 | var now = Date.now()
20 | var url = new URL(req.url)
21 |
22 | // 1. fixed http URL
23 | // Just keep syncing with location.protocol
24 | // fetch(httpURL) belongs to active mixed content.
25 | // And fetch(httpRequest) is not supported yet.
26 | url.protocol = self.location.protocol
27 |
28 | // 2. add query for caching-busting.
29 | // Github Pages served with Cache-Control: max-age=600
30 | // max-age on mutable content is error-prone, with SW life of bugs can even extend.
31 | // Until cache mode of Fetch API landed, we have to workaround cache-busting with query string.
32 | // Cache-Control-Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=453190
33 | if (url.hostname === self.location.hostname) {
34 | url.search += (url.search ? '&' : '?') + 'cache-bust=' + now
35 | }
36 | return url.href
37 | }
38 |
39 | /**
40 | * @Lifecycle Activate
41 | * New one activated when old isnt being used.
42 | *
43 | * waitUntil(): activating ====> activated
44 | */
45 | self.addEventListener('activate', event => {
46 | event.waitUntil(self.clients.claim())
47 | })
48 |
49 | /**
50 | * @Functional Fetch
51 | * All network requests are being intercepted here.
52 | *
53 | * void respondWith(Promise
r)
54 | */
55 | self.addEventListener('fetch', event => {
56 | // Skip some of cross-origin requests, like those for Google Analytics.
57 | if (HOSTNAME_WHITELIST.indexOf(new URL(event.request.url).hostname) > -1) {
58 | // Stale-while-revalidate
59 | // similar to HTTP's stale-while-revalidate: https://www.mnot.net/blog/2007/12/12/stale
60 | // Upgrade from Jake's to Surma's: https://gist.github.com/surma/eb441223daaedf880801ad80006389f1
61 | const cached = caches.match(event.request)
62 | const fixedUrl = getFixedUrl(event.request)
63 | const fetched = fetch(fixedUrl, { cache: 'no-store' })
64 | const fetchedCopy = fetched.then(resp => resp.clone())
65 |
66 | // Call respondWith() with whatever we get first.
67 | // If the fetch fails (e.g disconnected), wait for the cache.
68 | // If there’s nothing in cache, wait for the fetch.
69 | // If neither yields a response, return offline pages.
70 | event.respondWith(
71 | Promise.race([fetched.catch(_ => cached), cached])
72 | .then(resp => resp || fetched)
73 | .catch(_ => { /* eat any errors */ })
74 | )
75 |
76 | // Update the cache with the version we fetched (only for ok status)
77 | event.waitUntil(
78 | Promise.all([fetchedCopy, caches.open(RUNTIME)])
79 | .then(([response, cache]) => response.ok && cache.put(event.request, response))
80 | .catch(_ => { /* eat any errors */ })
81 | )
82 | }
83 | })
--------------------------------------------------------------------------------
/docs/zh-cn/English/english-document.md:
--------------------------------------------------------------------------------
1 | # 查看文档
2 |
3 | >**需要提前安装好[mitmproxy依赖](zh-cn/quick-start/quick-start.md)**
4 | >>|**查看方式**|**查看指令**|**说明**|
5 | >>|:----:|:--------:|:--------:|
6 | >>|**生成静态HTML**|**
`python -m pydoc -w mitmproxy.net.http`
`python -m pydoc -w mitmproxy.coretypes.multidict`
**|**默认生成到当前目录**|
7 | >>|**在线查看文档**|**`python -m pydoc -p 55555`**|**如果55555端口被占用(可修改)
启动55555端口成功后
访问[mitmproxy.net.http](http://127.0.0.1:55555/mitmproxy.net.http.html)
访问[mitmproxy.coretypes.multidict](http://127.0.0.1:55555/mitmproxy.coretypes.multidict.html)**|
--------------------------------------------------------------------------------
/docs/zh-cn/Object/Message/Message.md:
--------------------------------------------------------------------------------
1 | # Request和Response同时继承Message对象
2 | ## Message对象属性
3 |
4 | >>|**Message对象属性**|**作用**|**例子**|
5 | >>|:----:|:--------:|:--------:|
6 | >>|**`flow.request/flow.response.headers`**|**获取协议头**|**直接`headers`即可**|
7 | >>|**`flow.request/flow.response.http_version`**|**获取HTTP协议版本**|**直接使用
`http_version`**|
8 | >>|**`flow.request/flow.response.content`**|**未压缩的HTTP消息主体
(以bytes为单位)**|**直接`content`即可**|
9 | >>|**`flow.request/flow.response.raw_content`**|**可能被压缩过的HTTP消息主体
(以bytes为单位)**|**直接使用
`raw_content`**|
10 | >>|**`flow.request/flow.response.text`**|**返回text**|**直接使用`text`即可**|
11 | >>|**`flow.request/flow.response.timestamp_start`**|**获取request第一个字节的
时间戳**|**直接使用`timestamp_start`**|
12 | >>|**`flow.request/flow.response.timestamp_end`**|**获取request最后一个字节的
时间戳**|**直接使用
`timestamp_end`**|
13 | >>|**`flow.request/flow.response.trailers`**|**获取request的trailers
Trailer规定哪个标头
用作分块消息后的元信息**|**直接`trailers`即可**|
14 |
15 |
16 | ## **Message对象方法**
17 | >>|**Message对象方法**|**作用**|**例子**|
18 | >>|:--------:|:--------:|:----------:|
19 | >>|**`flow.request/flow.response.decode(self, strict=True)`**|**根据当前request的
Content-Encoding标头进行解码
当Content-Encoding标头不存在
并且strict=True时
即触发ValueError异常**|**直接`decode()`即可**|
20 | >>|**`flow.request/flow.response.encode(self, e)`**|**对当前request进行编码
编码格式有:
"gzip", "deflate", "identity", "br"**|**直接使用`encode('gzip')`**|
21 | >>|**`flow.request/flow.response.get_state(self)`**|**获取request的状态**|**直接使用`get_state()`**|
22 | >>|**`flow.request/flow.response.set_state(self, state)`**|**设置request的状态**|**直接使用`set_state(state)`
要和`get_state()`
配合使用**|
23 | >>|**`flow.request/flow.response.get_content(self, strict: bool = True) -> bytes`**|**使用内容编码标头
(例如gzip)解码的
request消息正文**|**直接使用
`get_content()`
返回二进制数据**|
24 | >>|**`flow.request/flow.response.set_content(self, value: Union[bytes, NoneType]) -> None`**|**设置request的
二进制数据**|**直接使用`set_content(b'xxx')`
可用`get_content()`查看新内容**|
25 | >>|**`flow.request/flow.response.get_text(self, strict: bool = True) -> Union[str, NoneType]`**|**使用内容编码标头
(例如gzip)和Content-Encoding标头字符集
解码的HTTP消息正文**|**此方法可以自动解码
源码有多种方案解码
直接使用`get_text()`
返回str**|
26 | >>|**`flow.request/flow.response.set_text(self, text: Union[str, NoneType]) -> None`**|**设置request的text**|**直接使用`set_text('xxx')`
可用`get_text()`
查看新内容**|
--------------------------------------------------------------------------------
/docs/zh-cn/Object/MultiDictView/MultiDictView.md:
--------------------------------------------------------------------------------
1 | # Request和Response同时继承MultiDictView对象
2 | ## MultiDictView方法
3 |
4 | >**Request和Response都能使用MultiDictView对象
即:`flow.request/flow.response.query`
因为Response通常没有query,所以我这里删掉了
假如你的URL为:https://xxx.com?xxx=xxx**
5 | >>|**MultiDictView对象方法**|作用
|**例子**|
6 | >>|:----:|:--------:|:--------:|
7 | >>|**`flow.request.query`**|**获取MultiDictView对象**|**直接返回
`MultiDictView[('data','xxx')]`**|
8 | >>|**`flow.request.query.items(self, multi=False)`**|**获取request的url参数所有键和值(元组形式)
默认False返回所有键和值(去重)
改为True则返回键的所有值**|**直接items()
返回可迭代对象
用for语句即可读取**|
9 | >>|**`flow.request.query.get(self, key, default=None)`**|**获取增加request的url参数
如果不存在这个键默认为None值**|**直接get('xxx')
查看内容请使用items()即可**|
10 | >>|**`flow.request.query.get_all(self, key)`**|**获取request的url参数
传递一个键名即可获取
不存在则返回空列表**|**直接`get_all('xxx')`
返回列表**|
11 | >>|**`flow.request.query.add(self, key, value)`**|**插入request的url参数
向后插入一个键和值**|**直接`add('xxx','xxx')`
查看内容请使用`items()`即可**|
12 | >>|**`flow.request.query.insert(self, index, key, value)`**|**插入request的url参数
在指定位置插入给键和值**|**直接`insert(0,'xxx','xxx')`
查看内容请使用`items()`即可**|
13 | >>|**`flow.request.query.keys(self, multi=False)`**|**获取request的url参数的键值
默认False返回键的一个重复值(键的唯一性)
改为True则返回键的一个值**|**直接keys()
直接返回generator生成器
用for语句即可读取**|
14 | >>|**`flow.request.query.values(self, multi=False)`**|**获取request的url参数的键值
默认False返回键的第一个值
改为True则返回键的所有值**|**直接values()
返回generator生成器
用for语句即可读取**|
15 | >>|**`flow.request.query.setdefault(self,key,default = None)`**|**设置默认值操作
增加request的url参数
如果不存在这个键默认为None值**|**直接`setdefault('xxx')`或者`setdefault('xxx','xxx')`
查看内容请使用`items()`即可**|
16 | >>|**`flow.request.query.set_all(self, key, values)`**|**修改request的url某个参数所有值**|**直接`set_all("xxx",["xxx"])`即可
**|
17 | >>|**`flow.request.query.clear(self)`**|**删除request的url所有参数**|**直接`clear()`
查看内容请使用`items()`即可**|
18 | >>|**`flow.request.query.popitem(self)`**|**弹栈操作
删除并返回request的url参数
没有参数即引发KeyError异常**|**直接`popitem()`
查看内容请使用`items()`即可**|
--------------------------------------------------------------------------------
/docs/zh-cn/Object/Request/Request.md:
--------------------------------------------------------------------------------
1 | ## Request对象属性
2 |
3 | >**假如你的URL为:https://xxx.com/xxx/xxx**
4 | >>|**Request对象属性**|**作用**|**例子**|
5 | >>|:----:|:--------:|:--------:|
6 | >>|**`flow.request`**|**获取mitmproxy.http.HTTPRequest对象**|**返回对象**|
7 | >>|**`flow.request.port`**|**获取request端口号**|**返回端口号**|
8 | >>|**`flow.request.url`**|**获取request的url**|**返回https://xxx.com**|
9 | >>|**`flow.request.pretty_url`**|**获取request的pretty_url
和普通url很类似
但这个主要用于
mitmproxy的透明模式**|**直接返回url**|
10 | >>|**`flow.request.host`**|**获取request的host**|**返回
xxx.com**|
11 | >>|**`flow.request.pretty_host`**|**获取当前request的pretty_host
和host_header很类似
但这个主要用于
mitmproxy的透明模式**|**返回
xxx.com**|
12 | >>|**`flow.request.host_header`**|**获取当前request的
host_header此属性是根据
headers的host进行映射的**|**返回
xxx.com**|
13 | >>|**`flow.request.method`**|**获取request的method**|**返回
GET、POST等等**|
14 | >>|**`flow.request.scheme`**|**获取request的scheme**|**返回
http、https等等协议**|
15 | >>|**`flow.request.path`**|**获取request的path**|**返回
URL的/xxx/xxx**|
16 | >>|**`flow.request.multipart_form`**|**获取request的多部分表单数据**|**返回
MultiDictView对象**|
17 | >>|**`flow.request.path_components`**|**获取request的url的路径(元组形式)**|**返回元组**|
18 | >>|**`flow.request.urlencoded_form`**|**获取当前request的url编码表单数据**|**返回
MultiDictView对象**|
19 | >>|**`flow.request.first_line_format`**|**根据[HTTP的规范](https://www.rfc-editor.org/rfc/rfc7230.txt)
origin-form和asterisk-form
将被判断为relative(相对的)**|**返回str**|
20 |
21 | ## Request对象方法
22 |
23 | >**假如你的URL为:https://xxx.com**
24 | >>|**Request对象方法**|作用
|**例子**|
25 | >>|:-------:|:----------:|:-----------:|
26 | >>|**`flow.request.text.replace(self, pattern, repl, flags=0, count=0)`**|**替换request的内容
pattern:被替换的内容(正则表达式模式)
repl:替换的内容
flags:标记数量
count:替换次数**|**常用于`text.replace('xxx','xxx')`
与get_text()或text属性配合使用即可**|
27 | >>|**`flow.request.make(method: str, url: str, content: Union[bytes, str] = '', headers: Union[mitmproxy.net.http.headers.Headers, Dict[Union[str, bytes], Union[str, bytes]], Iterable[Tuple[bytes, bytes]]] = ()) -> 'Request'`**|**生成新的request的
method、url、content、headers等等
用于修改或替换request
主要用途:捉弄别人**|**返回Request对象
直接使用
`flow.request.make(method='GET',url='https://xxx.com',headers={'xxx':'xxx'})`**|
28 | >>|**`flow.request.anticache(self)`**|**删除request可能产生的缓存
删除了协议头的ETags和If-Modified-Since**|**直接`anticache()`即可**|
29 | >>|**`flow.request.anticomp(self)`**|**删除request可能压缩数据资源的标头**|**直接`anticomp()`即可**|
30 | >>|**`flow.request.constrain_encoding(self)`**|**限制request的Accept-Encoding值
方便我们之后解码**|**直接`constrain_encoding()`即可**|
--------------------------------------------------------------------------------
/docs/zh-cn/Object/Response/Response.md:
--------------------------------------------------------------------------------
1 | ## Response对象属性
2 |
3 | >|**Response对象属性**|**作用**|**例子**|
4 | >|:----:|:--------:|:--------:|
5 | >|**`flow.response.status_code`**|**获取response的状态码**|**直接`status_code`即可**|
6 | >|**`flow.response.cookies`**|**获取response的cookies**|**返回MultiDictView对象
直接`flow.response.cookies`即可**|
7 | >|**`flow.response.reason`**|**获取response的reason
注意:HTTP/2不包括reason**|**返回MultiDictView对象
直接`flow.response.cookies`即可**|
8 |
9 | ## Response对象方法
10 |
11 | >|**Response对象方法**|作用
|**例子**|
12 | >|:----:|:--------:|:--------:|
13 | >|**`flow.response.text.replace(self, pattern, repl, flags=0, count=0)`**|**替换response的内容
pattern:被替换的内容(正则表达式模式)
repl:替换的内容
flags:标记数量
count:替换次数**|**常用于text.replace('xxx','xxx')
与get_text()或text属性
配合使用即可**|
14 | >|**`flow.response.make(status_code: int = 200, content: Union[bytes, str] = b'', headers: Union[mitmproxy.net.http.headers.Headers, Mapping[str, Union[str, bytes]], Iterable[Tuple[bytes, bytes]]] = ()) -> 'Response'`**|**生成新的response的
status_code、content、headers等等
用于修改或替换response
主要用途:捉弄别人**|**直接使用
`flow.response.make(status_code=200,content=b'',headers={'xxx':'xxx'})`
返回Response对象**|
15 | >|**`flow.response.refresh(self, now=None)`**|**让response响应进行重播
调整日期,过期和最后修改的标题
调整Cookie的到期时间**|**常用于`refresh(new_time)`
这个new_time可以和
Python的time模块配合
`new_time=time.time()`**|
--------------------------------------------------------------------------------
/docs/zh-cn/README.md:
--------------------------------------------------------------------------------
1 | #
2 | # **[哔哩哔哩作者:-相依-](https://space.bilibili.com/343154012)** **UPDATE 2021-3-22**
3 | >**由于mitmproxy[官方API文档说明](https://docs.mitmproxy.org/archive/v5/addons-overview/#addons),从v3版本开始就没有规范好API手册,只能通过pydoc查看最新代码规范。
所以小弟整理了与HTTP相关的API帮助大家处理抓包问题,本次翻译的是v5.3.0官方API文档。
如果我翻译或理解错了,请尝试查看旧版[v2.0.2官方API文档](https://docs.mitmproxy.org/archive/v2/index.html#document-scripting/api),感谢您的支持!**
4 |
5 | ## **[🎉Mitmproxy视频教学](https://www.bilibili.com/video/BV1Lv411a7CP)**
6 |
7 | ## 在线阅读
8 |
9 | > - **[⚡国内优先 Gitee 在线阅读](https://mochazi.gitee.io/mitmproxy-doc-cn)** | **[Gitee 仓库地址](https://gitee.com/mochazi/mitmproxy-doc-cn)**
10 | > - **[🎉国外优先 GitHub 在线阅读](https://mochazi.github.io/mitmproxy-doc-cn)** | **[GitHub 仓库地址](https://github.com/mochazi/mitmproxy-doc-cn)**
11 |
12 |
13 | ## 访问量统计
14 | 本站总访问量次
15 |
16 |
17 |
--------------------------------------------------------------------------------
/docs/zh-cn/quick-start/quick-start.md:
--------------------------------------------------------------------------------
1 | ## 项目版本
2 | 本项目用到的Python版本为3.7.9,如果出现不兼容情况,请尝试切换Python版本
3 |
4 | |**项目依赖**|**安装指令**|**项目使用版本**|
5 | |:----:|:--------:|:--------:|
6 | |**mitmproxy**|**pip install mitmproxy==5.3.0**|**5.3.0**|
7 |
8 | ## 简述对象用途
9 |
10 | |**对象名字**|**类型**|**作用**|
11 | |:----:|:--------:|:--------:|
12 | |**Request**|**HTTP请求类**|**发起request**|
13 | |**Response**|**HTTP响应类**|**接收response**|
14 | |**Message**|**HTTP信息类**|**处理HTTP信息**|
15 | |**MultiDictView**|**字典工具类**|**可迭代方便后续处理**|
16 |
17 | ## 官方HTTP模板
18 | >**以下是官方的[HTTP事件模板](https://docs.mitmproxy.org/archive/v5/addons-events/#http-events)
不过常用的只有request和response事件
所以我们要对模板删减一部分**
19 |
20 | ```python
21 | """HTTP-specific events."""
22 | import mitmproxy.http
23 |
24 |
25 | class Events:
26 | def http_connect(self, flow: mitmproxy.http.HTTPFlow):
27 | """
28 | An HTTP CONNECT request was received. Setting a non 2xx response on
29 | the flow will return the response to the client abort the
30 | connection. CONNECT requests and responses do not generate the usual
31 | HTTP handler events. CONNECT requests are only valid in regular and
32 | upstream proxy modes.
33 | """
34 |
35 | def requestheaders(self, flow: mitmproxy.http.HTTPFlow):
36 | """
37 | HTTP request headers were successfully read. At this point, the body
38 | is empty.
39 | """
40 |
41 | def request(self, flow: mitmproxy.http.HTTPFlow):
42 | """
43 | The full HTTP request has been read.
44 | """
45 |
46 | def responseheaders(self, flow: mitmproxy.http.HTTPFlow):
47 | """
48 | HTTP response headers were successfully read. At this point, the body
49 | is empty.
50 | """
51 |
52 | def response(self, flow: mitmproxy.http.HTTPFlow):
53 | """
54 | The full HTTP response has been read.
55 | """
56 |
57 | def error(self, flow: mitmproxy.http.HTTPFlow):
58 | """
59 | An HTTP error has occurred, e.g. invalid server responses, or
60 | interrupted connections. This is distinct from a valid server HTTP
61 | error response, which is simply a response with an HTTP error code.
62 | """
63 | ```
64 |
65 | ## 启动Mitmproxy
66 | >**我们根据官方插件开发的[教程](https://docs.mitmproxy.org/archive/v5/addons-overview/#anatomy-of-an-addon)
**
67 | >>|**名称**|**命名要求**|**类型**|**用途**|
68 | >>|:----:|:--------:|:--------:|:--------:|
69 | >>|**Counter**|**任意命名**|**class**|**插件实例**|
70 | >>|**addons**|**必须为addons**|**list**|**记录多个插件(任务列表)**|
71 |
72 | >**新建`addons.py`文件并写入以下内容
**
73 |
74 | ```python
75 | import mitmproxy.http
76 | from mitmproxy import ctx
77 |
78 | class Counter:
79 |
80 | def request(self, flow: mitmproxy.http.HTTPFlow):
81 |
82 | ctx.log.info('白色标准输出:{}'.format(flow.request.url))
83 | ctx.log.warn('黄色警告输出:{}'.format(flow.request.url))
84 | ctx.log.error('红色异常输出:{}'.format(flow.request.url))
85 |
86 | def response(self, flow: mitmproxy.http.HTTPFlow):
87 |
88 | print(flow.response.status_code)#获取网页状态码
89 |
90 | addons = [
91 | Counter()
92 | ]
93 | ```
94 |
95 | >**随后在终端输入`mitmweb -s addons.py`启动插件
**
96 | >**显示以下内容说明成功启动mitmproxy
**
97 | >**自动弹出`mitmweb`默认自带管理界面`http://127.0.0.1:8081`
**
98 |
99 | ```bash
100 | Web server listening at http://127.0.0.1:8081
101 | Loading script addons.py
102 | Proxy server listening at http://*:8080
103 | ```
104 |
105 | ## 连接Mitmproxy
106 |
107 | >**安装requests模块,用来发起HTTP请求并连接`8080`端口**
108 | ```bash
109 | pip install requests
110 | ```
111 | >**新建`http_demo.py`文件并写入以下内容**
112 | ```python
113 | import requests
114 |
115 | headers = {
116 | 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36'
117 | }
118 |
119 | proxies = {
120 | 'http':'127.0.0.1:8080',
121 | 'https':'127.0.0.1:8080',
122 | }
123 |
124 | url = 'https://www.baidu.com'
125 |
126 | html = requests.get(url,headers=headers,proxies = proxies,verify=False)
127 | print(html.status_code)
128 | ```
129 | >**浏览器访问`http://127.0.0.1:8081`进入`mitmweb`管理界面
**
130 | >**在终端输入`python http_demo.py`运行Python文件
**
131 | >**此时`mitmweb`管理界面就会出现抓包内容
**
--------------------------------------------------------------------------------