golang gin 代理和改包
说明
目前仅支持http协议,其他协议需要用socket
使用 gin 做客户端和服务端的中间代理
快速搭建环境
- 创建项目文件夹
创建 ginProxy 文件夹后,进入该文件夹
mkdir ginProxy
cd ginProxy
- 初始化mod
ginProxy 为包的名称,在该目录下会生成 go.mod 文件
go mod init ginProxy
- 下载安装 gin 框架
参数 -u 为本地有该包就更新,没有则下载
go get -u github.com/gin-gonic/gin
- 实现 gin 的 hello world
gin 实现代理
代理实现有多种方式
- 直接代理
不做任何修改,直接发往目标服务器
client --> request --> gin --> gin_request --> service --> gin_response --> gin --> response --> client
- 修改代理
修改请求内容再发往目标服务器,收到返回内容修改后再返回给客户端
client --> request --> gin --> modify_request --> gin_request --> service --> gin_response --> gin --> modify_response --> response --> client
- 返回代理
直接返回给客户端,不经过目标服务器,类似私服模式
这个就是传统的请求和回应,把代理当目标服务器
client --> request --> gin --> response --> client
直接代理
不做任何修改,直接把原始请求给代理请求 request = c.Request
c.Request 为 客户端发给 gin 的请求
request为 gin 向目标服务器的请求
router.POST("/test01", func(c *gin.Context) {
proxy := httputil.ReverseProxy{Director: func(request *http.Request) {
request = c.Request
}}
proxy.ServeHTTP(c.Writer, c.Request)
})
修改代理
- 修改请求头
获取请求头
c.GetHeader("sn")
修改请求头
c.Request.Header.Set("sn","123456789")
- 修改请求体
如果加密了需要先解密,修改后再加密
首先需要查看 body 的类型为 io.ReadCloser类型
Body io.ReadCloser
这里有个知识点:post 的 body 数据不是和 header 一起发送的,是分开来发送的。get 是一起发送的
所以需要把 body 数据给读取过来,存到内存中
接着对 body 数据进行操作,读完就可以关闭了
body,err := ioutil.ReadAll(c.Request.Body)
if err != nil{
panic(err)
}
if err := c.Request.Body.Close(); err != nil{
panic(err)
}
// 对 body 数据进行操作
对数据操作完之后,需要把数据发送给目标服务器,即创建 io.ReadCloser
等待服务端读取内存中的数据
也就是说每次请求响应的数据都要存到内存中,比较费内存
c.Request.Body = ioutil.NopCloser(bytes.NewReader(body))
- 修改响应头
如果加密了需要先解密,修改后再加密
目标服务器返回后的回调,response 即为目标服务器的响应
proxy.ModifyResponse = func(response *http.Response) error {
// 修改返回给客户端的 response
return nil
}
响应头和响应体的修改和上面请求的一样,把请求改为响应
比如获取响应头
response.Header.Get("k")
比如设置响应头
response.Header.Set("sn","123456789")
返回代理
标准的请求返回,查看 gin 文档
主要就是返回的内容要符合客户端的加密解密操作
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!