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文档

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 文档
主要就是返回的内容要符合客户端的加密解密操作

git项目地址

原文地址:https://www.cnblogs.com/GH-123/p/13566789.html