go gin框架做请求转发(代理 Proxy)

这篇博客介绍了如何使用Go语言的httputil库创建一个中间件,实现对外服务A对内服务B的请求转发。通过检查请求头中的'direct'字段,当其值为'lab'时,将请求的Scheme和Host替换,并添加特定查询参数。同时,展示了两种不同的实现方式,一种是直接使用httputil.ReverseProxy,另一种是自定义创建新的HTTP请求。代码示例清晰地展示了请求转发的完整流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

我现在有两个服务,简称 ABA 是对外开放的服务,存储了访问 B 所必须的参数,顾要通过 A 来做请求转发至 B

实现思路

其实就是根据指定规则,拦截请求,替换一下请求的地址,期间可以自行对请求返回结果拦截,做一些修改值之类的操作。

  1. server 服务做中间件,进行拦截。(我这边是根据请求头中的内容来进行拦截的,判断 header 中的 direct 的值是否为 lab
  2. 替换请求的 Scheme(如:http) 和 Host (如:www.baidu.com)
  3. 保证原请求的请求参数不变
  4. 返回请求结果

代码实现

  1. go 的官方仓库 httputil 封装了相关的方法 ReverseProxy
  2. 通过上述逻辑,自己简单封装下请求,根据需求进行相应的修改

直接上代码

httputil.ReverseProxy

func Proxy(c *gin.Context) {
	if c.GetHeader("direct") != "lab" {
		return
	}
	var proxyUrl = new(url.URL)
	proxyUrl.Scheme = "http"
	proxyUrl.Host = "172.16.60.161"
	//u.Path = "base" // 这边若是赋值了,做转发的时候,会带上path前缀,例: /hello -> /base/hello

	proxyUrl.RawQuery = url.QueryEscape("token=" + "VjouhpQHa6wgWvtkPQeDZbQd") // 和如下方式等价
	//var query url.Values
	//query.Add("token", "VjouhpQHa6wgWvtkPQeDZbQd")
	//u.RawQuery = query.Encode()

	proxy := httputil.NewSingleHostReverseProxy(proxyUrl)

	//proxy := httputil.ReverseProxy{}
	//proxy.Director = func(req *http.Request) {
	//	fmt.Println(req.URL.String())
	//	req.URL.Scheme = "http"
	//	req.URL.Host = "172.16.60.161"
	//	rawQ := req.URL.Query()
	//	rawQ.Add("token", "VjouhpQHa6wgWvtkPQeDZbQd")
	//	req.URL.RawQuery = rawQ.Encode()
	//}

	// proxy.ErrorHandler // 可以添加错误回调
	// proxy.Transport // 若有需要可以自定义 http.Transport


	proxy.ServeHTTP(c.Writer, c.Request)

	c.Abort()
}

自己简单实现

/ 也就是做简单的转发操作
func Proxy(c *gin.Context) {
	if c.GetHeader("direct") != "lab" {
		return
	}

	err := setTokenToUrl(c.Request.URL)
	if err != nil {
		c.String(http.StatusInternalServerError, fmt.Sprintf("填写的地址有误: %s", err.Error()))
		c.Abort()
		return
	}

	req, err := http.NewRequestWithContext(c, c.Request.Method, c.Request.URL.String(), c.Request.Body)
	if err != nil {
		c.String(http.StatusInternalServerError, err.Error())
		c.Abort()
		return
	}
	defer req.Body.Close()
	req.Header = c.Request.Header

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		c.String(http.StatusInternalServerError, err.Error())
		c.Abort()
		return
	}
	// header 也带过来
	for k :=  range resp.Header {
		for j := range resp.Header[k] {
			c.Header(k, resp.Header[k][j])
		}
	}
	extraHeaders := make(map[string]string)
	extraHeaders["direct"] = "lab"
	c.DataFromReader(resp.StatusCode, resp.ContentLength, resp.Header.Get("Content-Type"), resp.Body, extraHeaders)
	c.Abort()
}

func setTokenToUrl(rawUrl *url.URL) (error) {
	// 这边是从设置里拿代理值
	//equipment, err := proxy.GetEquipment()
	//if err != nil {
	//	return err
	//}
	proxyUrl := "http://172.16.60.161"
	token := "VjouhpQHa6wgWvtkPQeDZbQd"
	u, err := url.Parse(proxyUrl)
	if err != nil {
		return err
	}

	rawUrl.Scheme = u.Scheme
	rawUrl.Host = u.Host
	ruq := rawUrl.Query()
	ruq.Add("token", token)
	rawUrl.RawQuery = ruq.Encode()
	return nil
}
### Golang Gin 框架使用教程 #### 安装环境准备 为了能够顺利安装和使用Gin框架,需先确保已正确安装Golang。对于Golang的版本建议不低于1.15[^3]。 #### 安装Gin框架 通过`go get`命令来获取Gin库文件,这会自动将所需的依赖项一同下载下来: ```bash $ go get -u github.com/gin-gonic/gin ``` 如果遇到网络问题无法正常拉取资源,则可以通过配置GOPROXY指向国内镜像源解决此问题: ```bash $ go env -w GO111MODULE=on $ go env -w GOPROXY=https://goproxy.cn,direct ``` 以上操作完成后即完成了Gin框架的基础安装过程[^2]。 #### 创建第一个HTTP服务器实例 下面给出一段简单的代码用来创建基于Gin框架的Web服务端程序: ```go package main import ( "net/http" "github.com/gin-gonic/gin" ) func helloWorld(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "message": "Hello world!", }) } func main() { r := gin.Default() r.GET("/hello", helloWorld) r.Run(":8080") // 默认监听地址为localhost:8080 } ``` 这段代码定义了一个GET类型的API接口/hello,在接收到客户端请求时返回JSON格式的消息"Hello world!"给调用方[^1]。 #### 集成Swagger自动生成API文档 为了让开发者更加方便地维护RESTful API的设计说明以及测试在线调试功能,可以考虑集成Swagger工具来自动生成交互式的API文档。具体法是在项目里加入必要的模块支持,并按照官方指南完成相应设置即可实现这一目标[^5]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值