转到http,使用client.Do发送传入的http.request到其他服务器 [英] Go http, send incoming http.request to an other server using client.Do

查看:1455
本文介绍了转到http,使用client.Do发送传入的http.request到其他服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里我的用例



我们有一个服务foobar,它有两个版本传统 version_2_of_doom (都在进入)



为了从传统 version_2_of_doom ,我们希望第一次有两个版本并且有POST请求(因为这里只有一个POST API调用)收到两个。



我看到如何做到这一点。将会修改传统的代码在开始时的


  1. 处理程序,以便将请求复制到 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)
    //遗产代码




  2. 但它看起来不像这样简单

    它以失败, http:Request.RequestURI不能在客户端请求中设置。



    有没有一种众所周知的方法来做这种动作即转移而不触及) http.Request 到其他服务器?

    解决方案

    你需要将你想要的值复制到一个新的请求中。由于这与逆向代理非常类似,您可能需要查看net / http / httputil ReverseProxy



    创建一个新请求,并仅复制零件您要发送到下一台服务器的请求。如果你打算在两个地方使用它,你还需要读取并缓冲请求体:



    $ p $ func处理程序(w http。 ResponseWriter,req * http.Request){
    //如果我们想在这里读取它并在请求中发送
    //,我们需要缓冲正文。
    body,err:= ioutil.ReadAll(req.Body)
    if err!= nil {
    http.Error(w,err.Error(),http.StatusInternalServerError)
    返回
    }

    //你可以重新分配正文,如果你需要将它解析为多部分
    req.Body = ioutil.NopCloser(bytes.NewReader(body))

    //从客户端发送的原始RequestURI中创建一个新的url $ b $ url url:= fmt.Sprintf(%s://%s%s,proxyScheme,proxyHost,req。 RequestURI)

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

    //我们可能需要过滤一些头文件,否则我们可以使用浅拷贝
    // 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)
    返回
    }
    推迟resp.Body.Close()

    //遗产代码
    }


    Here my use case

    We have one services "foobar" which has two version legacy and version_2_of_doom (both in go)

    In order to make the transition from legacy to version_2_of_doom , we would like in a first time, to have the two version alongside, and have the POST request (as there's only one POST api call in this ) received on both.

    The way I see how to do it. Would be

    1. modifying the code of legacy at the beginning of the handler, in order to duplicate the request to 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 
      

    but it seems to not be as straightforward as this

    it fails with http: Request.RequestURI can't be set in client requests.

    Is there a well-known method to do this kind of action (i.e transfering without touching) a http.Request to an other server ?

    解决方案

    You need to copy the values you want into a new request. Since this is very similar to what a reverse proxy does, you may want to look at what "net/http/httputil" does for ReverseProxy.

    Create a new request, and copy only the parts of the request you want to send to the next server. You will also need to read and buffer the request body if you intend to use it both places:

    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
    }
    

    这篇关于转到http,使用client.Do发送传入的http.request到其他服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆