go 实现反向代理

正向代理和反向代理区别

正向代理
代理的是客户端,隐藏了客户端的真实IP,部署在客户端网络中,访问外部资源,例如通过代理访问外网。

反向代理
代理的是服务端,隐藏了服务端的真实IP,部署在服务端网络中,提供负载均衡,例如访问nginx。

实现反向代理

package main

import (
    "log"
    "net/http"
    "net/http/httputil"
    "net/url"
)

func main() {
    // 解析目标服务器地址
    targetURL, err := url.Parse("http://www.baidu.com")
    if err != nil {
        log.Fatal(err)
    }

	// 创建反向代理,监听在8081端口
    proxy := httputil.NewSingleHostReverseProxy(targetURL)
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        // 修改请求头,请求目的地址改成目标服务器地址
        r.Host = targetURL.Host
        // 将请求转发到目标服务器
        proxy.ServeHTTP(w, r)
    })
    log.Println("反向代理服务监听端口8081")
    log.Fatal(http.ListenAndServe(":8081", nil))
}
    

源码分析

func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy {
	director := func(req *http.Request) {
        // 重写请求URL
		rewriteRequestURL(req, target)
	}
	return &ReverseProxy{Director: director}
}

func rewriteRequestURL(req *http.Request, target *url.URL) {
	targetQuery := target.RawQuery
	req.URL.Scheme = target.Scheme
    // 重写req的Host,从而把请求转发到后端
	req.URL.Host = target.Host
	req.URL.Path, req.URL.RawPath = joinURLPath(target, req.URL)
	if targetQuery == "" || req.URL.RawQuery == "" {
		req.URL.RawQuery = targetQuery + req.URL.RawQuery
	} else {
		req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
	}
}

1. 使用ReverseProxy参数Director修改请求。

2. 设置Header中X-Forward-For值为代理ip。

3. 通过连接池向后端发起请求。

4. 使用ReverseProxy参数ModifyResponse修改响应。

5. 复制后端响应头部、状态码、响应体到代理。

 

 

posted on 2025-03-29 16:00  王景迁  阅读(59)  评论(0)    收藏  举报

导航