前言 说起反向代理,大家应该都不陌生,是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。常见的反向代理有 Nginx,HAProxy,Apisix 等。
接下来介绍如何使用 go 实现一个反向代理服务器。
golang 实现 使用 golang 实现反向代理非常简单,标准库 net/http/httputil 提供了反向代理的方法可以让我们方便的实现反向代理,使我们可以很快的实现一个简单的反向代理服务器。
package main import ( "log" "net/http" "net/http/httputil" "net/url" ) func NewProxy(targetHost string) (*httputil.ReverseProxy, error) { url, err := url.Parse(targetHost) if err != nil { return nil, err } return httputil.NewSingleHostReverseProxy(url), nil } func ProxyRequestHandler(proxy *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { proxy.ServeHTTP(w, r) } } func main() { proxy, err := NewProxy("https://overstarry.vip") if err != nil { panic(err) } http.HandleFunc("/", ProxyRequestHandler(proxy)) log.Fatal(http.ListenAndServe(":8080", nil)) } 这段代码将到达我们代理服务器的任何请求都会被代理到 https://overstarry.vip。我们运行代码,访问网站,发现 403 Forbidden 好像请求被拦截了,应该是源网站进行了请求校验,这该怎么处理呢?通过查阅资料得知,我们需要将 host 传递过去,修改后的代码如下:
package main import ( "log" "net/http" "net/http/httputil" "net/url" ) func NewProxy(targetHost string) (*httputil.ReverseProxy, error) { url, err := url.Parse(targetHost) if err != nil { return nil, err } return httputil.NewSingleHostReverseProxy(url), nil } func ProxyRequestHandler(proxy *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { r.Host = "overstarry.vip" proxy.ServeHTTP(w, r) } } func main() { proxy, err := NewProxy("https://overstarry.vip") if err != nil { panic(err) } http.HandleFunc("/", ProxyRequestHandler(proxy)) log.Fatal(http.ListenAndServe(":8080", nil)) } 现在运行代码即可正常访问了。
...