英文:
I can't change the Host header using reverse proxy
问题
我正在为我的后端构建一个反向代理,但我无法理解为什么即使我使用文档中看到的任何方法更改主机头,它也不会改变。
后端需要真实的主机来提供正确的内容。
以下是代码:
proxy := &httputil.ReverseProxy{
Director: func(req *http.Request) {
targetURL := url.URL{
Scheme: "http",
Host: "backend.com",
Path: req.URL.Path,
}
req.URL.Scheme = targetURL.Scheme
req.URL.Host = targetURL.Host
req.URL.Path = targetURL.Path
req.Header.Set("Host", targetURL.Host)
},
Transport: transport,
}
// 在本地端口上监听并提供无缓冲方法的反向代理
server := &http.Server{
Addr: "localhost:8080",
Handler: proxy,
}
fmt.Println("正在监听 :8080...")
err = server.ListenAndServe()
if err != nil {
fmt.Println(err)
}
英文:
I'm building a reverse proxy for my backend but I can't understand why even if I change the host header with any method I've seen in the documentation It won't change.
The backend need the real host in order to serve the right content.
Here is the code:
proxy := &httputil.ReverseProxy{
Director: func(req *http.Request) {
targetURL := url.URL{
Scheme: "http",
Host: "backend.com",
Path: req.URL.Path,
}
req.URL.Scheme = targetURL.Scheme
req.URL.Host = targetURL.Host
req.URL.Path = targetURL.Path
req.Header.Set("Host", targetURL.Host)
},
Transport: transport,
}
// Listen on a local port and serve the reverse proxy without buffer method
server := &http.Server{
Addr: "localhost:8080",
Handler: proxy,
}
fmt.Println("Listening on :8080...")
err = server.ListenAndServe()
if err != nil {
fmt.Println(err)
}
答案1
得分: 2
如果您可以使用go1.20中添加的(*ProxyRequest).SetURL,那么操作将非常简单:
proxy := &httputil.ReverseProxy{
Rewrite: func(pr *httputil.ProxyRequest) {
targetURL := url.URL{
Scheme: "http",
Host: "backend.com",
Path: req.URL.Path,
}
pr.SetURL(&targetURL)
},
Transport: transport,
}
有关更多信息,请参见此提案:net/http/httputil: replace Director with Rewrite。
如果无法升级到go1.20,以下是Director
的解决方法:
proxy := &httputil.ReverseProxy{
Director: func(req *http.Request) {
targetURL := url.URL{
Scheme: "http",
Host: "backend.com",
Path: req.URL.Path,
}
req.URL.Scheme = targetURL.Scheme
req.URL.Host = targetURL.Host
req.URL.Path = targetURL.Path
- req.Header.Set("Host", targetURL.Host)
+ req.Host = targetURL.Host
+ // 或者简单地:
+ // req.Host = ""
},
Transport: transport,
}
请参阅http.Request.Host的文档:
> 对于客户端请求,Host可选地覆盖要发送的Host标头。如果为空,Request.Write方法将使用URL.Host的值。
英文:
If you can use (*ProxyRequest).SetURL added in go1.20, it will be as easy as:
proxy := &httputil.ReverseProxy{
Rewrite: func(pr *httputil.ProxyRequest) {
targetURL := url.URL{
Scheme: "http",
Host: "backend.com",
Path: req.URL.Path,
}
pr.SetURL(&targetURL)
},
Transport: transport,
}
See this proposal for more information: net/http/httputil: replace Director with Rewrite.
In the case that it's impossible to upgrade to go1.20, here is a workaround for the Director
:
proxy := &httputil.ReverseProxy{
Director: func(req *http.Request) {
targetURL := url.URL{
Scheme: "http",
Host: "backend.com",
Path: req.URL.Path,
}
req.URL.Scheme = targetURL.Scheme
req.URL.Host = targetURL.Host
req.URL.Path = targetURL.Path
- req.Header.Set("Host", targetURL.Host)
+ req.Host = targetURL.Host
+ // or simply:
+ // req.Host = ""
},
Transport: transport,
}
See the doc for http.Request.Host:
> For client requests, Host optionally overrides the Host header to send. If empty, the Request.Write method uses the value of URL.Host.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论