{"id":13775818,"url":"https://github.com/qiyeboy/baseproxy","last_synced_at":"2025-04-09T07:09:52.403Z","repository":{"id":57414043,"uuid":"138246933","full_name":"qiyeboy/BaseProxy","owner":"qiyeboy","description":"Asynchronous HTTP/HTTPS proxy that intercepts and modifies messages(异步http/https代理,可拦截修改报文)","archived":false,"fork":false,"pushed_at":"2018-06-22T15:18:02.000Z","size":415,"stargazers_count":242,"open_issues_count":4,"forks_count":49,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-04-24T10:20:11.987Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/qiyeboy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-06-22T02:51:27.000Z","updated_at":"2024-04-15T07:43:46.000Z","dependencies_parsed_at":"2022-09-26T17:11:15.388Z","dependency_job_id":null,"html_url":"https://github.com/qiyeboy/BaseProxy","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qiyeboy%2FBaseProxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qiyeboy%2FBaseProxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qiyeboy%2FBaseProxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qiyeboy%2FBaseProxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/qiyeboy","download_url":"https://codeload.github.com/qiyeboy/BaseProxy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247994122,"owners_count":21030050,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T17:01:51.184Z","updated_at":"2025-04-09T07:09:52.380Z","avatar_url":"https://github.com/qiyeboy.png","language":"Python","funding_links":[],"categories":["\u003ca id=\"d03d494700077f6a65092985c06bf8e8\"\u003e\u003c/a\u003e工具"],"sub_categories":["\u003ca id=\"b6f25145e99ea944cbb528a24afaa0be\"\u003e\u003c/a\u003eHTTP\u0026\u0026HTTPS"],"readme":"# BaseProxy\n异步http/https代理,可拦截并修改报文Python,可以作为中间人工具.仅支持**py3.5+**.\n\u003cbr\u003e\n个人公众号如下,欢迎大家交流。\u003cbr\u003e\n![公众号](./img/qiye2.jpg)\n## 意义\nBaseProxy项目的本意是为了使HTTP/HTTPS拦截更加纯粹,更加易操作,学习成本更低。\n\u003cbr\u003e\n在Python领域,中间人工具非常强大和成功的是MitmProxy,但是有些地方不是很喜欢。\n- Windows上安装比较费时费力\n- 功能太多了,可惜我用不到这么多(似乎不是它的错，哈哈)\n- 随着版本升级,采用插件化框架,需要定制功能,需要写个插件成为它的一部分(我只是想集成它而已).\n\n因此BaseProxy就诞生了,不仅支持HTTPS透明传输,还支持HTTP/HTTPS拦截,简单易用,可以很好地集成到你们的项目中。\n## 安装\n安装非常简单,本项目已经发布到PyPI中...\n```\npip3 install baseproxy\n```\n## 使用配置\n### 启动baseproxy\n在test文件夹下，有很多测试用例。以startserver.py为例。\n```\nfrom baseproxy.proxy import AsyncMitmProxy\n\nbaseproxy = AsyncMitmProxy(https=True)\n\nbaseproxy.serve_forever()\n```\n使用上述代码,就可以将HTTPServer运行起来了.对代码的解释如下:\n\n- ```https=True```是对https进行解密;```https=False```是对于https实行透传\n- baseproxy默认运行在8788端口,如果想改变端口的话,修改为```AsyncMitmProxy(server_addr=('',port),https=True)```.\n\n运行结果如下:\n```\n[2018-06-22 18:46:32] INFO HTTPServer is running at address(  , 8788 )......\n```\n\n### 安装CA证书\n1.将chrome浏览器代理服务器设置为127.0.0.1:8788,推荐使用SwitchyOmega插件.\n\n![代理设置](./img/daili.jpg)\n\n2.设置好代理,并将baseproxy运行后,访问www.baidu.com.\n\n![百度](./img/baidu.jpg)\n\n3.这时候访问被拒绝,需要安装证书.在当前网页访问 baseproxy.ca,下载证书.\n\n![ca](./img/casite.jpg)\n\n![cafile](./img/cafile.jpg)\n\n4.双击下载的证书,并安装到合法机构中.\n\n![ca2](./img/cainstall.jpg)\n\n![ca3](./img/trustCA.jpg)\n\n![ca3](./img/casure.jpg)\n\n5.接着访问百度就可以了.\n\n![baidu](./img/baidu2.jpg)\n\n**注意：只有```https=True```时,才需要安装CA证书。**\n\n\n## 开发\n经过上一步的使用配置,baseproxy已经可以正常运行了,但是这样是远远不够的.baseproxy还提供了接口,方便开发者对http请求和响应进行修改.\n### 接口\nbaseproxy提供了两个接口,一个是修改请求,一个是修改响应.\n\n#### 拦截请求\n```\nclass ReqIntercept(InterceptPlug):\n\n    def deal_request(self,request):\n        pass\n\n\n```\n对于请求的拦截,需要继承ReqIntercept类,并重写其中的deal_request函数.在deal_request函数的最后,需要将修改后的request参数返回出去.\n如果想抛弃这个请求,直接返回None.\n\n#### request参数\ndeal_request函数中的request参数类型为Request类\n\u003cbr\u003e\n**成员变量**\n\n| Name        | 类型    |  含义  |\n| --------   | -----:   | :----: |\n| hostname        | str     |   域名    |\n| port        | int      |   端口    |\n| command        | str      |   请求类型    |\n| path        | str      |   请求路径    |\n| request_version        | str      |   HTTP协议版本    |\n\n**成员函数**\n\n```\n\n    def set_headers(self,headers)\n     - headers:类型为dict\n     - 用于设置头部\n```\n```\n    def get_header(self,key):\n    - key:类型为str\n    - 用于获取指定头部,返回str\n```\n```\n    def get_headers(self):\n    - 用于获取整个头部,返回为dict\n```\n```\n    def set_header(self,key,value):\n    - 头部 key,类型str\n    - 头部 value,类型str\n    - 用于设置头信息\n```\n```\n    def get_body_data(self):\n    - 获取请求体内容,返回类型为bytes\n```\n\n```\n    def set_body_data(self,body):\n    - 设置请求体内容,body类型为bytes\n\n```\n\n#### 拦截响应\n```\nclass RspIntercept(InterceptPlug):\n\n    def deal_response(self,response):\n        pass\n\n```\n对于响应的拦截,需要继承RspIntercept类,并重写其中的deal_response函数.在deal_response函数的最后,需要将修改后的response参数返回出去.\n如果想抛弃这个响应,直接返回None.\n\n#### response参数\ndeal_response函数中的response参数类型为Response类\n\u003cbr\u003e\n**成员变量**\n\n| Name        | 类型    |  含义  |\n| --------   | -----:   | :----: |\n| hostname        | str     |   域名    |\n| port        | int      |   端口    |\n| status        | int      |   状态码   |\n| reason        | str      |   状态描述    |\n| response_version        | str      |   HTTP协议版本    |\n| request        | Request      |   响应对应的请求实例    |\n\n\n**成员函数**\n\n```\n\n    def set_headers(self,headers)\n     - headers:类型为dict\n     - 用于设置头部\n```\n```\n    def get_header(self,key):\n    - key:类型为str\n    - 用于获取指定头部,返回str\n```\n```\n    def get_headers(self):\n    - 用于获取整个头部,返回为dict\n```\n```\n    def set_header(self,key,value):\n    - 头部 key,类型str\n    - 头部 value,类型str\n    - 用于设置头信息\n```\n```\n    def get_body_data(self):\n    - 获取响应体内容,返回类型为bytes\n```\n\n```\n    def set_body_data(self,body):\n    - 设置响应体内容,body类型为bytes\n\n```\n```\n    def get_body_str(self,decoding=None):\n    - decoding:编码,默认为None,内部采用chardet探测\n    - 返回响应体,类型为str.如果无法解码,返回None\n\n```\n```\n    def set_body_str(self,body_str,encoding=None):\n    - encoding:编码,默认为None,内部采用chardet探测\n    - 设置响应体,body_str类型为str\n```\n\n### 注册拦截插件\n将拦截类完成后，需要注册到baseproxy中,需要调用AsyncMitmProxy的register函数.示例如下:\n```\nfrom baseproxy.proxy import ReqIntercept, RspIntercept, AsyncMitmProxy\n__author__ = 'qiye'\n__date__ = '2018/6/21 23:35'\n\nclass DebugInterceptor(ReqIntercept, RspIntercept):\n    def deal_request(self, request):\n        return request\n\n    def deal_response(self, response):\n        return response\n\nif __name__==\"__main__\":\n\n    baseproxy = AsyncMitmProxy(https=False)\n    baseproxy.register(DebugInterceptor)\n    baseproxy.serve_forever()\n\n```\n## 小例子\n将淘宝中的所有产品图片换成**我公众号的二维码**.代码在test文件夹的replace_image.py中,内容如下:\n```\nfrom baseproxy.proxy import RspIntercept, AsyncMitmProxy\n\n\n\nclass ImageInterceptor( RspIntercept):\n\n    def deal_response(self, response):\n        if response.get_header(\"Content-Type\") and 'image' in response.get_header(\"Content-Type\"):\n            with open(\"../img/qiye2.jpg\",'rb') as f:\n                response.set_body_data(f.read())\n        return response\n\n\nif __name__ == \"__main__\":\n    baseproxy = AsyncMitmProxy(https=True)\n    baseproxy.register(ImageInterceptor)\n    baseproxy.serve_forever()\n```\n效果如下:\n\n![替换](./img/erweima.jpg)\n\n\n\n## 参考项目\n[MitmProxy](https://github.com/mitmproxy/mitmproxy)\n\u003cbr\u003e\n[proxy2](https://github.com/inaz2/proxy2)\n\n\n\n\n\n#\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqiyeboy%2Fbaseproxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fqiyeboy%2Fbaseproxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqiyeboy%2Fbaseproxy/lists"}