go gin フレームワークは転送を要求します (プロキシ Proxy)

背景

A現在、略してと と呼ばれる 2 つのサービスがありますBA外部に公開されたサービスであり、Bアクセスに必要なパラメータが格納されており、お客様はを通じてAリクエストを転送する必要がありますB

実装のアイデア

実際には、指定されたルールに従ってリクエストをインターセプトし、リクエストされたアドレスを置き換えるわけですが、この間、リクエスト返された結果を自分でインターセプト、値を変更するなどの操作を行うことができます。

  1. serverこのサービスはミドルウェアとして機能し、インターセプトします。(リクエストヘッダーの内容に基づいてインターセプトし、の値headerが であるかどうかを判断します)directlab
  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
}

おすすめ

転載: blog.csdn.net/DisMisPres/article/details/119041567