golang 实现HTTP代理和反向代理

Posted pu369

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang 实现HTTP代理和反向代理相关的知识,希望对你有一定的参考价值。

正向代理

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
", req.Method, req.Host, req.RemoteAddr)

    transport := http.DefaultTransport

    // step 1
    outReq := new(http.Request)
    *outReq = *req // this only does shallow copies of maps

    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)
}

上面的代码运行之后,会在本地的 8080 端口启动代理服务。修改浏览器的代理为 127.0.0.1::8080 再访问http网站,可以验证代理正常工作,也能看到它在终端打印出所有的请求信息。

如果了解 HTTPS 协议的话,你会明白这种模式下是无法完成 HTTPS 握手的,虽然代理可以和真正的服务器建立连接(知道了对方的公钥和证书),但是代理无法代表服务器和客户端建立连接,因为代理服务器无法知道真正服务器的私钥。

反向代理

编写反向代理按照上面的思路当然没有问题,只需要在第二步的时候,根据之前的配置修改 outReq 的 URL Host 地址可以了。不过 Golang 已经给我们提供了编写代理的框架: httputil.ReverseProxy 。我们可以用非常简短的代码来实现自己的代理,而且内部的细节问题都已经被很好地处理了。

package main

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

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        director := func(req *http.Request) {
            req = r
            req.URL.Scheme = "http"
            req.URL.Host = r.Host
        }
        proxy := &httputil.ReverseProxy{Director: director}
        proxy.ServeHTTP(w, r)
    })

    log.Fatal(http.ListenAndServe(":8888", nil))
}

感觉用法与正向代理没区别,也是设置浏览器代理地址后,用于访问http网站

 用代理访问HTTPS

待完善

 

参考:

https://blog.csdn.net/mengxinghuiku/article/details/65448600

https://www.jianshu.com/p/f868c88b45e1

https://studygolang.com/articles/11967?fr=sidebar

https://studygolang.com/articles/12525?fr=sidebar

https://segmentfault.com/a/1190000003735562

以上是关于golang 实现HTTP代理和反向代理的主要内容,如果未能解决你的问题,请参考以下文章

golang实现正/反向代理服务

golang http proxy反向代理

golang 反向代理reverseproxy源码分析

5分钟用Go语言(Golang)实现一个HTTP代理(Proxy)

『GCTT 出品』用不到 100 行的 Golang 代码实现 HTTP(S) 代理

使用golang反向代理统计api访问次数