转到http,使用client.Do发送传入的http.request到其他服务器 [英] Go http, send incoming http.request to an other server using client.Do
问题描述
这里我的用例
我们有一个服务foobar,它有两个版本传统
和 version_2_of_doom
(都在进入)
为了从传统
到 version_2_of_doom
,我们希望第一次有两个版本并且有POST请求(因为这里只有一个POST API调用)收到两个。
我看到如何做到这一点。将会修改传统
的代码在开始时的
-
处理程序,以便将请求复制到
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)
//遗产代码
modifying the code of
legacy
at the beginning of the handler, in order to duplicate the request toversion_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不能在客户端请求中设置。
有没有一种众所周知的方法来做这种动作即转移而不触及) http.Request
到其他服务器?
你需要将你想要的值复制到一个新的请求中。由于这与逆向代理非常类似,您可能需要查看net / http / httputil为 ReverseProxy
。
创建一个新请求,并仅复制零件您要发送到下一台服务器的请求。如果你打算在两个地方使用它,你还需要读取并缓冲请求体:
$ p $
//如果我们想在这里读取它并在请求中发送
//,我们需要缓冲正文。
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
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屋!