当前位置:  开发笔记 > 编程语言 > 正文

转到http,使用client.Do将传入的http.request发送到其他服务器

如何解决《转到http,使用client.Do将传入的http.request发送到其他服务器》经验,为你挑选了2个好方法。

这是我的用例

我们有一个服务"foobar"有两个版本legacyversion_2_of_doom (都在去)

为了使从过渡legacyversion_2_of_doom,我们想在第一时间,有两个版本的旁边,并有POST请求(因为在这个只有一个POST API调用)对两个接收.

我看待怎么做的方式.将会

    修改legacy 处理程序开头的代码,以便将请求复制到version_2_of_doom

     func(w http.ResponseWriter, req *http.Request) {
         req.URL.Host = "v2ofdoom.local:8081"
         req.Host = "v2ofdoom.local:8081"
         client := &http.Client{}
         client.Do(req)
         // legacy code 
    

但它似乎并不像这样直截了当

它失败了 http: Request.RequestURI can't be set in client requests.

是否有一种众所周知的方法来执行此类操作(即,不接触地转移)http.Request到另一台服务器?



1> JimB..:

您需要将所需的值复制到新请求中.由于这与反向代理的功能非常相似,因此您可能需要查看"net/http/httputil"的用途ReverseProxy.

创建新请求,并仅复制要发送到下一个服务器的请求部分.如果您打算在两个地方使用它,您还需要读取并缓冲请求正文:

func handler(w http.ResponseWriter, req *http.Request) {
    // we need to buffer the body if we want to read it here and send it
    // in the request. 
    body, err := ioutil.ReadAll(req.Body)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    // you can reassign the body if you need to parse it as multipart
    req.Body = ioutil.NopCloser(bytes.NewReader(body))

    // create a new url from the raw RequestURI sent by the client
    url := fmt.Sprintf("%s://%s%s", proxyScheme, proxyHost, req.RequestURI)

    proxyReq, err := http.NewRequest(req.Method, url, bytes.NewReader(body))

    // We may want to filter some headers, otherwise we could just use a shallow copy
    // proxyReq.Header = req.Header
    proxyReq.Header = make(http.Header)
    for h, val := range req.Header {
        proxyReq.Header[h] = val
    }

    resp, err := httpClient.Do(proxyReq)
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadGateway)
        return
    }
    defer resp.Body.Close()

    // legacy code
}



2> helmbert..:

根据我的经验,实现此目的的最简单方法是简单地创建新请求并将所需的所有请求属性复制到新请求对象中:

func(rw http.ResponseWriter, req *http.Request) {
    url := req.URL
    url.Host = "v2ofdoom.local:8081"

    proxyReq, err := http.NewRequest(req.Method, url.String(), req.Body)
    if err != nil {
        // handle error
    }

    proxyReq.Header.Set("Host", req.Host)
    proxyReq.Header.Set("X-Forwarded-For", req.RemoteAddr)

    for header, values := range req.Header {
        for _, value := range values {
            proxyReq.Header.Add(header, value)
        }
    }

    client := &http.Client{}
    proxyRes, err := client.Do(proxyReq)

    // and so on...

这种方法的好处是不修改原始请求对象(可能你的处理函数或生活在堆栈中的任何中间件函数仍然需要原始对象?).

推荐阅读
kikokikolove
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有