猿问

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

我想实现一个HTTP请求和响应系统,用于

client ------> A ----------> B --------> (request) HTTPserver
client <------ A <---------- B <-------- (response) HTTPserver
  1. 客户端使用任何 HTTP 方法(POST、PUT 等)向 A 发送 HTTP 请求

  2. 然后A读取请求正文对其进行加密,然后将其转发到B 3 B,然后解密读取HTTP请求正文

  3. B然后用收到的解密体作为有效载荷准备一个HTTP请求并发送到HTTP服务器。5 然后,HTTP 服务器响应 B。

  4. 然后 B 对来自 HTTP 服务器的响应进行加密,然后转发到 A。

  5. 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 client

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


defer req.Body.Close()


// encrypt req.Body

object, _ := enc.Encrypt(bodybytes)


// serialize object

serialized, _ := object.CompactSerialize()


// prepare forwarding message

msg := 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))


我的问题是

  1. 如何将代理 B 中的代理ServHTTP“res”中的“respmsgbytes”写回代理A?

  2. 如何从代理服务器 B 读取响应数据,然后将响应发送到客户端?

有什么帮助吗?我留下了错误检查以使代码简短。


UYOU
浏览 205回答 1
1回答

至尊宝的传说

你可以使用 httputil你可以做类似下面的事情。对于代理 A:const (&nbsp; ServerB = "<address of B>"&nbsp; Port = "<proxy A port>")func main() {&nbsp; // start server&nbsp; http.HandleFunc("/", proxyPass)&nbsp; log.Fatal(http.ListenAndServe(":" + Port, nil))}func proxyPass(res http.ResponseWriter, req&nbsp; *http.Request) {&nbsp; // Encrypt Request here&nbsp; // ...&nbsp; url, _ := url.Parse(ServerB)&nbsp; proxy := httputil.NewSingleHostReverseProxy(url)&nbsp; proxy.ServeHTTP(res, req)}&nbsp;对于代理 B:const (&nbsp; Server = "<address of server>"&nbsp; Port = "<proxy B port>")func main() {&nbsp; // start server&nbsp; http.HandleFunc("/", proxyPass)&nbsp; log.Fatal(http.ListenAndServe(":" + Port, nil))}func proxyPass(res http.ResponseWriter, req&nbsp; *http.Request) {&nbsp; // Decrypt Request here&nbsp; // ...&nbsp; url, _ := url.Parse(Server)&nbsp; proxy := httputil.NewSingleHostReverseProxy(url)&nbsp; proxy.ServeHTTP(res, req)}&nbsp;编辑:要处理每个代理的请求正文,您可以查看此内容。或者,我认为基于当前要求构建新要求应该没有坏处,如下所示:func proxyPass(res http.ResponseWriter, req&nbsp; *http.Request) {&nbsp; &nbsp; body, _ := ioutil.ReadAll(req.Body)&nbsp; &nbsp; data := string(body)&nbsp; &nbsp; // process data here&nbsp; &nbsp; req, _ = http.NewRequest(req.Method, req.URL.String(), strings.NewReader(data))&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; u, _ := url.Parse(Server)&nbsp; &nbsp; proxy := httputil.NewSingleHostReverseProxy(u)&nbsp; &nbsp; proxy.ServeHTTP(res, req)}这可以在两个代理上完成。编辑:代理响应可以使用 ReverseProxy.ModifyResponse 进行更新。你可以这样使用它:func proxyPass(res http.ResponseWriter, req *http.Request) {&nbsp; &nbsp; ....&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; proxy := httputil.NewSingleHostReverseProxy(url)&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; proxy.ModifyResponse = func(response *http.Response) error {&nbsp; &nbsp; &nbsp; &nbsp; // Read and update the response here&nbsp; &nbsp; &nbsp; &nbsp; // The response here is response from server (proxy B if this is at proxy A)&nbsp; &nbsp; &nbsp; &nbsp; // It is a pointer, so can be modified to update in place&nbsp; &nbsp; &nbsp; &nbsp; // It will not be called if Proxy B is unreachable&nbsp; &nbsp; }&nbsp; &nbsp; proxy.ServeHTTP(res, req)}
随时随地看视频慕课网APP

相关分类

Go
我要回答