如何调试httputil.NewSingleHostReverseProxy [英] How to debug httputil.NewSingleHostReverseProxy

查看:577
本文介绍了如何调试httputil.NewSingleHostReverseProxy的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题:

  1. 我正在寻求一个HTTPS地址.
  2. 我想看看为什么要删除 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.
  3. 我想跟踪代理从中返回的呼叫 当我取消注释行req.Host = req.URL.Host时,httputil. NewSingleHostReverseProxy正在显示.
  1. I'm fowarding to a HTTPS address.
  2. 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 a 404.
  3. I want to trace the call the proxy returned from httputil. NewSingleHostReverseProxy is making when I uncommment the line req.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屋!

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