如何调试httputil.NewSingleHostReverseProxy [英] How to debug httputil.NewSingleHostReverseProxy
问题描述
问题:
- 我正在寻求一个HTTPS地址.
- 我想看看为什么要删除
req.Host = req.URL.Host
导致它失败.而不是返回{"Code":"OBRI.FR.Request.Invalid","Id":"c37baec213dd1227","Message":"An error happened when parsing the request arguments","Errors":[{"ErrorCode":"UK.OBIE.Header.Missing","Message":"Missing request header 'x-fapi-financial-id' for method parameter of type String","Url":"https://docs.ob.forgerock.financial/errors#UK.OBIE.Header.Missing"}]}
它返回一个404
. - 我想跟踪代理从中返回的呼叫
当我取消注释行
req.Host = req.URL.Host
时,httputil. NewSingleHostReverseProxy
正在显示.
- I'm fowarding to a HTTPS address.
- I want to see why removing
req.Host = req.URL.Host
causes it to fail. Instead of returning{"Code":"OBRI.FR.Request.Invalid","Id":"c37baec213dd1227","Message":"An error happened when parsing the request arguments","Errors":[{"ErrorCode":"UK.OBIE.Header.Missing","Message":"Missing request header 'x-fapi-financial-id' for method parameter of type String","Url":"https://docs.ob.forgerock.financial/errors#UK.OBIE.Header.Missing"}]}
it returns a404
. - I want to trace the call the proxy returned from
httputil. NewSingleHostReverseProxy
is making when I uncommment the linereq.Host = req.URL.Host
.
这样发出请求:
$ curl http://localhost:8989/open-banking/v2.0/accounts
以及下面的代码(main.go
):
package main
import (
"log"
"net/http"
"net/http/httputil"
"net/url"
)
func main() {
target, err := url.Parse("https://rs.aspsp.ob.forgerock.financial:443")
log.Printf("forwarding to -> %s%s\n", target.Scheme, target.Host)
if err != nil {
log.Fatal(err)
}
proxy := httputil.NewSingleHostReverseProxy(target)
http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
// https://stackoverflow.com/questions/38016477/reverse-proxy-does-not-work
// https://forum.golangbridge.org/t/explain-how-reverse-proxy-work/6492/7
// https://stackoverflow.com/questions/34745654/golang-reverseproxy-with-apache2-sni-hostname-error
req.Host = req.URL.Host // if you remove this line the request will fail... I want to debug why.
proxy.ServeHTTP(w, req)
})
err = http.ListenAndServe(":8989", nil)
if err != nil {
panic(err)
}
}
推荐答案
将proxy.Transport字段设置为在委托默认传输之前转储请求的实现:
Set the proxy.Transport field to an implementation that dumps the request before delegating to the default transport:
package main
import (
"fmt"
"log"
"net/http"
"net/http/httputil"
"net/url"
)
type DebugTransport struct{}
func (DebugTransport) RoundTrip(r *http.Request) (*http.Response, error) {
b, err := httputil.DumpRequestOut(r, false)
if err != nil {
return nil, err
}
fmt.Println(string(b))
return http.DefaultTransport.RoundTrip(r)
}
func main() {
target, _ := url.Parse("https://example.com:443")
log.Printf("forwarding to -> %s\n", target)
proxy := httputil.NewSingleHostReverseProxy(target)
proxy.Transport = DebugTransport{}
http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
req.Host = req.URL.Host
proxy.ServeHTTP(w, req)
})
log.Fatal(http.ListenAndServe(":8989", nil))
}
该程序的输出如下所示:
The output from this program looks something like this:
2018/10/26 13:06:35 forwarding to -> https://example.com:443
GET / HTTP/1.1
Host: example.com:443
User-Agent: HTTPie/0.9.4
Accept: */*
Accept-Encoding: gzip, deflate
X-Forwarded-For: 127.0.0.1
或者,在删除请求主机分配后:
Or, after removing the req.Host assignment:
2018/10/26 13:06:54 forwarding to -> https://example.com:443
GET / HTTP/1.1
Host: localhost:8989
User-Agent: HTTPie/0.9.4
Accept: */*
Accept-Encoding: gzip, deflate
X-Forwarded-For: 127.0.0.1
由于Web服务器经常使用Host标头将请求路由到正确的虚拟主机或后端服务器,因此有意义的是,意外的Host标头(在上面的示例中为"localhost:8989")导致服务器做出响应带有404.
Since the Host header is very often used by webservers to route the request to the correct virtual host or backend server, it makes sense that an unexpected Host header ("localhost:8989" in the example above) causes the server to respond with 404.
通常使用Director
函数通过httputil.ReverseProxy设置Host标头:
Setting the Host header with httputil.ReverseProxy is typically done with the Director
function:
target, err := url.Parse("https://example.com:443")
if err != nil {
log.Fatal(err)
}
log.Printf("forwarding to -> %s\n", target)
proxy := httputil.NewSingleHostReverseProxy(target)
d := proxy.Director
proxy.Director = func(r *http.Request) {
d(r) // call default director
r.Host = target.Host // set Host header as expected by target
}
log.Fatal(http.ListenAndServe(":8989", proxy))
这篇关于如何调试httputil.NewSingleHostReverseProxy的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!