【发布时间】:2019-03-30 09:21:49
【问题描述】:
我基本上是在尝试编写一个反向代理服务器,以便当我 curl localhost:8080/get 时,它将请求代理到 https://nghttp2.org/httpbin/get。
注意:上面列出的https://nghttp2.org/httpbin/get 服务是http/2。但是这种行为也会发生在 http/1 上,例如 https://httpbin.org/get。
我为此使用httputil.ReverseProxy,并且我正在重写URL,同时自定义Host 标头以不将localhost:8080 泄漏到实际后端。
但是,无论我在标头上设置多少次,请求仍然会以Host: localhost:8080 到达后端。同样,我使用mitmproxy 窥探请求,看起来net/http.Client 将:authority 伪标头设置为localhost:8080
这是我的源代码:
package main
import (
"log"
"net/http"
"net/http/httputil"
)
func main() {
proxy := &httputil.ReverseProxy{
Transport: roundTripper(rt),
Director: func(req *http.Request) {
req.URL.Scheme = "https"
req.URL.Host = "nghttp2.org"
req.URL.Path = "/httpbin" + req.URL.Path
req.Header.Set("Host", "nghttp2.org") // <--- I set it here first
},
}
log.Fatal(http.ListenAndServe(":8080", proxy))
}
func rt(req *http.Request) (*http.Response, error) {
log.Printf("request received. url=%s", req.URL)
req.Header.Set("Host", "nghttp2.org") // <--- I set it here as well
defer log.Printf("request complete. url=%s", req.URL)
return http.DefaultTransport.RoundTrip(req)
}
// roundTripper makes func signature a http.RoundTripper
type roundTripper func(*http.Request) (*http.Response, error)
func (f roundTripper) RoundTrip(req *http.Request) (*http.Response, error) { return f(req) }
当我查询curl localhost:8080/get 时,请求被代理到https://nghttp2.org/httpbin/get。回显的响应清楚地表明,我设置 Host 标头的指令没有做任何事情:
{
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip",
"Host": "localhost:8080",
"User-Agent": "curl/7.54.0"
},
"origin": "2601:602:9c02:16c2:fca3:aaab:3914:4a71",
"url": "https://localhost:8080/httpbin/get"
}
mitmproxy snooping 还清楚地表明该请求是在 :authority 伪标头设置为 localhost:8080 的情况下发出的:
【问题讨论】:
标签: go