基于 Gin 的 HTTP 代理 demo

news2024/11/17 13:41:20

上次用 TCP 模拟了一个 HTTP 代理之后,感觉那样还是太简陋了,想着是不是可以用框架来做一个有点实际用处的东西。所以,就思索如何用 golang 的 Gin 框架来实现一个?嗯,对的你没有听错,是 gin 框架。你可能会疑惑,它不是 Web 框架吗,怎么可以用来做代理软件呢?哈哈,其实仔细想一想就明白了。我已经说过了,HTTP 代理的本质其实就是一个 HTTP 服务器!所以,我只要想办法让它来处理所有的路由就行了!

经过思考之后,我想到了 404 这个东西,通常对于一个 Web 服务来说,它就是不存在的路由。也就是说:
存在的路由 + 不存在的路由 = 全部的路由
对于一个 Web 服务,我们是有明确的接口(路由)的,所以会定义很多存在的路由。但是对于一个代理服务器来说,它根本不关心你的路由是什么,也就不需要存在的路由(你根本不知道用户会访问哪些路由),所以我们只需要处理不存在的路由即可。这里不存在的路由是指,不被 Web 服务处理的路由。
这样描述可能会有些困惑,那么就直说好了,我的想法是:在 Gin 框架中,不定义路由,这样全部的路由都会被认为是不存在的路由了,然后在专门处理 404 的方法中对所有的路由进行处理。相当于通过一个巧妙的方法,从而达到处理所有路由的目的,这样利用它来做一个 HTTP 代理就没有任何问题了。

代码

package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()
	r.NoRoute(routeProxy)  // 路由代理 handler
	r.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.Request
	go 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.StatusCode
	c.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())
}

注意:这里似乎也不需要这个默认的 /,因为代理的路由和不代理的路由是有区别的。

代理设置

请添加图片描述

这里 http=127.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 代理和改包

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1200605.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java 进阶篇】Java与JQuery选择器:解锁前端开发的魔法大门

在前端开发的世界中,选择器是我们与HTML文档进行互动的钥匙,而Java和JQuery则为我们提供了强大的工具,使得前端开发不再是一个艰深的谜题。本篇博客将围绕Java与JQuery选择器展开,深入解析选择器的奥秘,为你打开前端开…

体验版CorelDRAW2023矢量图话题工具

在当今数字化时代,图形设计已经成为了各行各业不可或缺的一部分。无论是企业的品牌标识、广告宣传,还是个人的插画作品、名片设计,都需要一个强大而多功能的设计软件来实现。而CorelDRAW正是这样一款令人惊叹的工具,它不仅提供了丰…

vue设计原理-带你重走vue诞生路程

我们首先看下面这个小demo demo源码: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" conten…

Python开发者的利器:掌握多种执行JS的方法

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com JavaScript&#xff08;JS&#xff09;是一种常用的脚本语言&#xff0c;通常用于网页开发&#xff0c;但有时也需要在Python中执行或调用JavaScript代码。这种需求可能是因为希望与网页进行交互&#xff0c;或者…

机器学习数据预处理——Word2Vec的使用

引言&#xff1a; Word2Vec 是一种强大的词向量表示方法&#xff0c;通常通过训练神经网络来学习词汇中的词语嵌入。它可以捕捉词语之间的语义关系&#xff0c;对于许多自然语言处理任务&#xff0c;包括情感分析&#xff0c;都表现出色。 代码&#xff1a; 重点代码&#…

【数据结构】树与二叉树(十二):二叉树的递归创建(算法CBT)

文章目录 5.2.1 二叉树二叉树性质引理5.1&#xff1a;二叉树中层数为i的结点至多有 2 i 2^i 2i个&#xff0c;其中 i ≥ 0 i \geq 0 i≥0。引理5.2&#xff1a;高度为k的二叉树中至多有 2 k 1 − 1 2^{k1}-1 2k1−1个结点&#xff0c;其中 k ≥ 0 k \geq 0 k≥0。引理5.3&…

【Redis系列】Redis的核心命令(上)

哈喽&#xff0c;大家好&#xff0c;我是小浪。那么上篇博客教会了大家如何在Linux上安装Redis&#xff0c;那么本篇博客就要正式开始学习Redis啦&#xff0c;跟着俺的随笔往下看~ 1、启动Redis 那么如何启动Redis呢&#xff1f;最常用的是以下这个命令&#xff1a; redis-cl…

“艾迪-东软杯”第六届武汉理工大学新生程序设计竞赛

A.Capoos Acronym Zero 题目描述 yz 和他的朋友 ea 和 zech 一起养了一群 Capoo。 这些 Capoo 非常聪明&#xff0c;但不知道为什么&#xff0c;它们并没有从三人那里学到怎么写算法题&#xff0c;而是出于某种原因开始研究语言学&#xff0c;并发明了一套自己的暗语。这门暗语…

设计模式之十一:代理模式

代理可以控制和管理访问。 RMI提供了客户辅助对象和服务辅助对象&#xff0c;为客户辅助对象创建和服务对象相同的方法。RMI的好处在于你不必亲自写任何网络或I/O代码。客户程序调用远程方法就和运行在客户自己本地JVM对对象进行正常方法调用一样。 步骤一&#xff1a;制作远程…

【C++初阶】类与对象(三)

目录 一、再谈构造函数1.1 初始化列表1.1.1 初始化列表写法1.1.2 哪些成员要使用初始化列表 1.2 初始化列表的特点1.2.1 队列类问题解决1.2.2 声明顺序是初始化列表的顺序 1.3 explicit关键字1.3.1 explicit关键字的作用 二、static成员2.1 类的静态成员概念2.2 类里创建了多少…

C++ 模板保姆级详解——template<class T>(什么是模板?模板分哪几类?模板如何应用?)

目录 一、前言 二、 什么是C模板 &#x1f4a6;泛型编程的思想 &#x1f4a6;C模板的分类 三、函数模板 &#x1f4a6;函数模板概念 &#x1f4a6;函数模板格式 &#x1f4a6;函数模板的原理 &#x1f4a6;函数模板的实例化 &#x1f34e;隐式实例化 &#x1f349;显式实…

Halcon WPF 开发学习笔记(4):Halcon 锚点坐标打印

文章目录 专栏前言锚点二次开发添加回调函数辅助Model类 下集预告 专栏 Halcon开发 博客专栏 WPF/HALCON机器视觉合集 前言 Halcon控件C#开发是我们必须掌握的&#xff0c;因为只是单纯的引用脚本灵活性过低&#xff0c;我们要拥有Halcon辅助开发的能力 锚点开发是我们常用的…

记录一次某某虚拟机的逆向

导语 学了一段时间的XPosed&#xff0c;发现XPosed真的好强&#xff0c;只要技术强&#xff0c;什么操作都能实现... 这次主要记录一下我对这款应用的逆向思路 apk检查 使用MT管理器检查apk的加壳情况 发现是某数字的免费版本 直接使用frida-dexdump 脱下来后备用 应用分…

【ATTCK】MITRE Caldera - 测试数据泄露技巧

CALDERA是一个由python语言编写的红蓝对抗工具&#xff08;攻击模拟工具&#xff09;。它是MITRE公司发起的一个研究项目&#xff0c;该工具的攻击流程是建立在ATT&CK攻击行为模型和知识库之上的&#xff0c;能够较真实地APT攻击行为模式。 通过CALDERA工具&#xff0c;安全…

Git版本控制系统之分支与标签(版本)

目录 一、Git分支&#xff08;Branch&#xff09; 1.1 分支作用 1.2 四种分支管理策略 1.3 使用案例 1.3.1 指令 1.3.2 结合应用场景使用 二、Git标签&#xff08;Tag&#xff09; 2.1 标签作用 2.2 标签规范 2.3 使用案例 2.3.1 指令 2.3.2 使用示例 一、Git分支&…

55基于matlab的1.高斯噪声2.瑞利噪声3.伽马噪声4.均匀分布噪声5.脉冲(椒盐)噪声

基于matlab的1.高斯噪声2.瑞利噪声3.伽马噪声4.均匀分布噪声5.脉冲&#xff08;椒盐&#xff09;噪声五组噪声模型&#xff0c;程序已调通&#xff0c;可直接运行。 55高斯噪声、瑞利噪声 (xiaohongshu.com)

“第六十六天”

这个我记得是有更优解的&#xff0c;不过还是明天发吧&#xff0c;明天想一想&#xff0c;看看能不能想起来 #include<string.h> int main() {char a[201] { 0 };char b[201] { 0 };scanf("%s %s", a, b);int na strlen(a);int nb strlen(b);int i 0, j …

基于SpringBoot+Vue的在线学习平台系统

基于SpringBootVue的在线学习平台系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootMyBatisVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 用户界面 登录界面 管理员界面 摘要 本文设计并实现了一套基于Spri…

C语言——贪吃蛇

一. 游戏效果 贪吃蛇 二. 游戏背景 贪吃蛇是久负盛名的游戏&#xff0c;它也和俄罗斯⽅块&#xff0c;扫雷等游戏位列经典游戏的⾏列。 贪吃蛇起源于1977年的投币式墙壁游戏《Blockade》&#xff0c;后移植到各种平台上。具体如下&#xff1a; 起源。1977年&#xff0c;投币式…