福州网站开发培训,南宁做自适应网站,外贸网络营销培训,南通网站建设服务公司上次用 TCP 模拟了一个 HTTP 代理之后#xff0c;感觉那样还是太简陋了#xff0c;想着是不是可以用框架来做一个有点实际用处的东西。所以#xff0c;就思索如何用 golang 的 Gin 框架来实现一个#xff1f;嗯#xff0c;对的你没有听错#xff0c;是 gin 框架。你可能会…上次用 TCP 模拟了一个 HTTP 代理之后感觉那样还是太简陋了想着是不是可以用框架来做一个有点实际用处的东西。所以就思索如何用 golang 的 Gin 框架来实现一个嗯对的你没有听错是 gin 框架。你可能会疑惑它不是 Web 框架吗怎么可以用来做代理软件呢哈哈其实仔细想一想就明白了。我已经说过了HTTP 代理的本质其实就是一个 HTTP 服务器所以我只要想办法让它来处理所有的路由就行了
经过思考之后我想到了 404 这个东西通常对于一个 Web 服务来说它就是不存在的路由。也就是说: 存在的路由 不存在的路由 全部的路由 对于一个 Web 服务我们是有明确的接口路由的所以会定义很多存在的路由。但是对于一个代理服务器来说它根本不关心你的路由是什么也就不需要存在的路由你根本不知道用户会访问哪些路由所以我们只需要处理不存在的路由即可。这里不存在的路由是指不被 Web 服务处理的路由。 这样描述可能会有些困惑那么就直说好了我的想法是在 Gin 框架中不定义路由这样全部的路由都会被认为是不存在的路由了然后在专门处理 404 的方法中对所有的路由进行处理。相当于通过一个巧妙的方法从而达到处理所有路由的目的这样利用它来做一个 HTTP 代理就没有任何问题了。
代码
package mainimport (fmtiolognet/httpstringsgithub.com/gin-gonic/gin
)func main() {r : gin.Default()r.NoRoute(routeProxy) // 路由代理 handlerr.GET(/, routeProxy) // 默认就有一个 / 路由所以把它也在路由代理中处理r.Run(:8000) // listen and serve on 0.0.0.0:8080 (for windows localhost:8080)
}// 这样就可以处理所有的路由情况了
func routeProxy(c *gin.Context) {// 代理接收到请求将其发出然后再返回对应的响应。req : c.Requestgo resolveReq(req) // 看看这个请求干了什么注意不能代理自己否则会有问题的newReq, _ : http.NewRequest(req.Method, req.URL.String(), req.Body)resp, err : http.DefaultClient.Do(newReq)if err ! nil {log.Fatal(err)}defer resp.Body.Close()data, err : io.ReadAll(resp.Body)if err ! nil {log.Fatal(err)}code : resp.StatusCodec.Status(code) // 响应状态码for k, v : range resp.Header {c.Header(k, strings.Join(v, ,))}c.Header(Server, CrazyDragonHttpProxy) // 篡改一个响应回复c.Writer.Write(data) // 响应数据
}func resolveReq(req *http.Request) {fmt.Printf(Method: %s, Host: %s, URL: %s\n, req.Method, req.Host, req.URL.String())
}
注意这里似乎也不需要这个默认的 /因为代理的路由和不代理的路由是有区别的。
代理设置 这里 http127.0.0.1这样就只会代理 http 协议不会处理 https 协议。因为我这里只是简单的 demo我也不想去处理 https那样太麻烦了我也不是很了解具体怎么做。使用 Fiddler 进行抓包设置时如果需要抓包 https 就需要安装它的证书你就知道很麻烦了。
注意它现在是一个代理服务器了所以你不能访问它自己不然就是代理服务器代理自己了。这里没对这个做处理所以就会报错。 测试
现在想要找一个 http 的网站来测试真的是麻烦了找了好久才发现一个 http 的网站毕竟现在还用 http 的网站真的是太稀少了。 然后就出现问题了我的电脑风扇开始狂啸CPU 使用率飙升。然后就是打印上面这些东西了所以应该就是代理服务器又把请求转发给了自己然后系统可能就维持了大量的连接导致 CPU 使用率飙升。我开始以为是我的 http.DefaultClient 代码的问题因为它的默认配置似乎会使用系统的代理。但是我又一想不对呀因为我并不是在系统之中我在容器里面呢我现在把本地开发环境卸载了所以我是在容器中进行开发的。不过我又想到虽然我在容器中但是 docker 还是在系统中的。 所以这个网络请求可能就是下图这样的红色是用户请求蓝色是代理的请求它循环了然后导致了问题。 所以我又想了想解决办法就是还是回到 Windows 本机上运行才行。但是因为本地已经没有了开发环境所以再另辟蹊径我只需要在 Windows 上执行就行了并不需要在 Winwos 上面编译。所以让我们来交叉编译一个 Windows 的版本吧。
不过这玩意在 docker 容器里面呢我还得拿出去才行那怎么办才好呢你听没有听过一个叫 docker cp 的命令不过根本不需要那么麻烦因为我这个目录是挂载进来的我直接去我的挂载目录就行了哈哈。 演示
终于是演示成功了不过我发现它还是会因为无法处理 https 而终止如果错误了我就简单终止了程序当然了你可以不处理直接返回就行了。https 的那个 connect 方法这玩意真的和乌云一样正常的 web 开发用不到它所以遇到了也就没法处理了我只知道它是代理服务器建立隧道用的其它的不清楚。因为我前面那样设置我以为是可以跳过 https 协议的而且我的其它 https 页面是可以正常访问的不过不知道为什么总有几个还是往代理服务器发送它处理不了这个东西导致代理崩溃了。 PS 我刚开始在寻找那个循环请求的问题时发现了一个老哥写的相似主题的文章。不过他这个就早多了好几年前了。不过我这里最主要的想法是关于 404 的处理他做的依然是关于指定路由的处理。不过他使用那个工具直接发送请求还是值得参考的但是因为这毕竟只是一个玩具还是不宜过度深入为好哈哈。
golang gin 代理和改包