为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 Go 中实现 HTTP 转发代理

如何在 Go 中实现 HTTP 转发代理

Go
UYOU 2022-08-24 18:41:40
我想实现一个HTTP请求和响应系统,用于client ------> A ----------> B --------> (request) HTTPserver client <------ A <---------- B <-------- (response) HTTPserver客户端使用任何 HTTP 方法(POST、PUT 等)向 A 发送 HTTP 请求然后A读取请求正文对其进行加密,然后将其转发到B 3 B,然后解密读取HTTP请求正文B然后用收到的解密体作为有效载荷准备一个HTTP请求并发送到HTTP服务器。5 然后,HTTP 服务器响应 B。然后 B 对来自 HTTP 服务器的响应进行加密,然后转发到 A。A 还解密来自 B 的响应,然后将响应发送回客户端。我根据前面的建议实现了以下目标。ProxyA:const (  ServerB = "<address of B>"  Port = "<proxy A port>")func main() {  // start server  http.HandleFunc("/", proxyPass)  log.Fatal(http.ListenAndServe(":" + Port, nil))}func proxyPass(res http.ResponseWriter, req  *http.Request) {  // read request body from clientbodybytes, _ := ioutil.ReadAll(req.Body)defer req.Body.Close()// encrypt req.Bodyobject, _ := enc.Encrypt(bodybytes)// serialize objectserialized, _ := object.CompactSerialize()// prepare forwarding messagemsg := message{reformatedData: serialized}// encode message msgbytes, _ := json.Marshal(&msg)req.ContentLength = int64(len(msgbytes))req.Body = ioutil.NopCloser(bytes.NewBuffer(msgbytes))// How do I read the response data from proxy server B and then send// response to the client....   url, _ := url.Parse(ServerB)  proxy := httputil.NewSingleHostReverseProxy(url)  proxy.ServeHTTP(res, req)}For proxy B:const (  Server = "<address of server>"  Port = "<proxy B port>")func main() {  // start server  http.HandleFunc("/", proxyPass)  log.Fatal(http.ListenAndServe(":" + Port, nil))}func proxyPass(res http.ResponseWriter, req  *http.Request) {  var msg message  HTTPServerurl := http://xxxxx  // read request body  bodybytes, _ := ioutil.ReadAll(req.Body)    req.ContentLength = int64(len(bodybytes))  req.Body = ioutil.NopCloser(bytes.NewBuffer(bodybytes))我的问题是如何将代理 B 中的代理ServHTTP“res”中的“respmsgbytes”写回代理A?如何从代理服务器 B 读取响应数据,然后将响应发送到客户端?有什么帮助吗?我留下了错误检查以使代码简短。
查看完整描述

1 回答

?
至尊宝的传说

TA贡献1789条经验 获得超10个赞

你可以使用 httputil

你可以做类似下面的事情。

对于代理 A:


const (

  ServerB = "<address of B>"

  Port = "<proxy A port>"

)


func main() {

  // start server

  http.HandleFunc("/", proxyPass)

  log.Fatal(http.ListenAndServe(":" + Port, nil))

}


func proxyPass(res http.ResponseWriter, req  *http.Request) {

  // Encrypt Request here

  // ...


  url, _ := url.Parse(ServerB)

  proxy := httputil.NewSingleHostReverseProxy(url)

  proxy.ServeHTTP(res, req)

对于代理 B:


const (

  Server = "<address of server>"

  Port = "<proxy B port>"

)


func main() {

  // start server

  http.HandleFunc("/", proxyPass)

  log.Fatal(http.ListenAndServe(":" + Port, nil))

}


func proxyPass(res http.ResponseWriter, req  *http.Request) {

  // Decrypt Request here

  // ...


  url, _ := url.Parse(Server)

  proxy := httputil.NewSingleHostReverseProxy(url)

  proxy.ServeHTTP(res, req)

编辑:

要处理每个代理的请求正文,您可以查看此内容。或者,我认为基于当前要求构建新要求应该没有坏处,如下所示:


func proxyPass(res http.ResponseWriter, req  *http.Request) {

    body, _ := ioutil.ReadAll(req.Body)

    data := string(body)


    // process data here


    req, _ = http.NewRequest(req.Method, req.URL.String(), strings.NewReader(data))

    

    u, _ := url.Parse(Server)

    proxy := httputil.NewSingleHostReverseProxy(u)

    proxy.ServeHTTP(res, req)

}

这可以在两个代理上完成。


编辑:

代理响应可以使用 ReverseProxy.ModifyResponse 进行更新。

你可以这样使用它:


func proxyPass(res http.ResponseWriter, req *http.Request) {

    ....

    

    proxy := httputil.NewSingleHostReverseProxy(url)

    

    proxy.ModifyResponse = func(response *http.Response) error {

        // Read and update the response here


        // The response here is response from server (proxy B if this is at proxy A)

        // It is a pointer, so can be modified to update in place

        // It will not be called if Proxy B is unreachable

    }


    proxy.ServeHTTP(res, req)

}


查看完整回答
反对 回复 2022-08-24
  • 1 回答
  • 0 关注
  • 204 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信