网络代理于网络转发区别
网络代理:
用户不直接连接服务器,网络代理去连接,获取数据后返回给用户
网络转发:
是路由器对报文的转发操作,中间可能对数据包修改
网络代理类型:
正向代理:
实现一个web浏览器代理:
代码实现一个web浏览器代理:
代码实现:
package main import ( "fmt" "io" "net" "net/http" "strings" ) type Pxy struct{} func (p *Pxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { fmt.Printf("Received request %s %s %s\n", req.Method, req.Host, req.RemoteAddr) transport := http.DefaultTransport // step 1,浅拷贝对象,然后就再新增属性数据 outReq := new(http.Request) *outReq = *req if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil { if prior, ok := outReq.Header["X-Forwarded-For"]; ok { clientIP = strings.Join(prior, ", ") + ", " + clientIP } outReq.Header.Set("X-Forwarded-For", clientIP) } // step 2, 请求下游 res, err := transport.RoundTrip(outReq) if err != nil { rw.WriteHeader(http.StatusBadGateway) return } // step 3, 把下游请求内容返回给上游 for key, value := range res.Header { for _, v := range value { rw.Header().Add(key, v) } } rw.WriteHeader(res.StatusCode) io.Copy(rw, res.Body) res.Body.Close() } func main() { fmt.Println("Serve on :8080") http.Handle("/", &Pxy{}) http.ListenAndServe("0.0.0.0:8080", nil) }
反向代理:
如何实现一个反向代理:
- 这个功能比较复杂,我们先实现一个简版的http反向代理。
- 代理接收客户端请求,更改请求结构体信息
- 通过一定的负载均衡算法获取下游服务地址
- 把请求发送到下游服务器,并获取返回的内容
- 对返回的内容做一些处理,然后返回给客户端
启动两个http服务(真是服务地址)
127.0.0.1:2003
127.0.0.1:2004
package main import ( "fmt" "io" "log" "net/http" "os" "os/signal" "syscall" "time" ) func main() { rs1 := &RealServer{Addr: "127.0.0.1:2003"} rs1.Run() rs2 := &RealServer{Addr: "127.0.0.1:2004"} rs2.Run() //监听关闭信号 quit := make(chan os.Signal) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit } type RealServer struct { Addr string } func (r *RealServer) Run() { log.Println("Starting httpserver at " + r.Addr) mux := http.NewServeMux() mux.HandleFunc("/", r.HelloHandler) mux.HandleFunc("/base/error", r.ErrorHandler) server := &http.Server{ Addr: r.Addr, WriteTimeout: time.Second * 3, Handler: mux, } go func() { log.Fatal(server.ListenAndServe()) }() } func (r *RealServer) HelloHandler(w http.ResponseWriter, req *http.Request) { //127.0.0.1:8008/abc?sdsdsa=11 //r.Addr=127.0.0.1:8008 //req.URL.Path=/abc fmt.Println(req.Host) upath := fmt.Sprintf("http://%s%s\n", r.Addr, req.URL.Path) realIP := fmt.Sprintf("RemoteAddr=%s,X-Forwarded-For=%v,X-Real-Ip=%v\n", req.RemoteAddr, req.Header.Get("X-Forwarded-For"), req.Header.Get("X-Real-Ip")) io.WriteString(w, upath) io.WriteString(w, realIP) } func (r *RealServer) ErrorHandler(w http.ResponseWriter, req *http.Request) { upath := "error handler" w.WriteHeader(500) io.WriteString(w, upath) }