dst8922 2016-02-18 11:40
浏览 180
已采纳

在Go中无法与httputil.ReverseProxy同时使用自定义RoundTrip和Dial

I'm writing a reverse proxy server in Go using the core net/http/httputil/ReverseProxy library. I already use a custom Director and I need to define my own RoundTrip and Dial for the Transport.

I'm able to use custom Dial like this:

transport := &http.Transport{
    Dial: func(network, addr string) (net.Conn, error) {
        lgr.Println("running custom magic below")
        // custom magic
        return net.Dial(network, addr)
    },
}
res := &httputil.ReverseProxy{Director: director, Transport: transport}
return res

So I created a custom transport that embeds http.Transport like this:

type customTransport struct {
    http.Transport
}

func (t *customTransport) RoundTrip(req *http.Request) (*http.Response, error) {
    res, err := http.DefaultTransport.RoundTrip(req)
    lgr.Println("checking the response")
    // check the response
    return res, err
}

And I tried to use it instead of the default Transport in this way:

transport := &customTransport{http.Transport{
    Dial: func(network, addr string) (net.Conn, error) {
        lgr.Println("running custom magic below")
        // custom magic
        return net.Dial(network, addr)
    },
}}
res := &httputil.ReverseProxy{Director: director, Transport: transport}

The problem is that while my custom RoundTrip works fine, the Dial stopped working now and no custom magic is done anymore.

When I log transport.Dial right after it is assigned, I see its address in memory. When I log my RevereProxy.Transport, which the function above returns in res, I even see the same address there:

fmt.Printf("%#v", transport.Dial)
2016/02/18 12:11:48.401245 main.go:76: (func(string, string) (net.Conn, error))(0x4039a0)
fmt.Printf("%#v", proxy.Transport)
2016/02/18 12:11:48.401403 main.go:100: &main.customTransport{Transport:http.Transport{idleMu:sync.Mutex{state:0, sema:0x0}, wantIdle:false, idleConn:map[http.connectMethodKey][]*http.persistConn(nil), idleConnCh:map[http.connectMethodKey]chan *http.persistConn(nil), reqMu:sync.Mutex{state:0, sema:0x0}, reqCanceler:map[*http.Request]func()(nil), altMu:sync.RWMutex{w:sync.Mutex{state:0, sema:0x0}, writerSem:0x0, readerSem:0x0, readerCount:0, readerWait:0}, altProto:map[string]http.RoundTripper(nil), Proxy:(func(*http.Request) (*url.URL, error))(nil), Dial:(func(string, string) (net.Conn, error))(0x4039a0), DialTLS:(func(string, string) (net.Conn, error))(nil), TLSClientConfig:(*tls.Config)(nil), TLSHandshakeTimeout:0, DisableKeepAlives:false, DisableCompression:false, MaxIdleConnsPerHost:0, ResponseHeaderTimeout:0, ExpectContinueTimeout:0, TLSNextProto:map[string]func(string, *tls.Conn) http.RoundTripper(nil), nextProtoOnce:sync.Once{m:sync.Mutex{state:0, sema:0x0}, done:0x0}, h2transport:(*http.http2Transport)(nil)}}

Anyway, it seems that the core net.Dial method is called instead of my custom Dial and I really don't have a clue why. :-( Any ideas would be highly appreciated! Thanks!

  • 写回答

1条回答 默认 最新

  • duanqu9292 2016-02-18 16:49
    关注

    You're defining a custom Transport, but calling RoundTrip on the http.DefaultTransport. You need to call RoundTrip on the embedded Transport:

    type customTransport struct {
        *http.Transport
    }
    
    func (t *customTransport) RoundTrip(req *http.Request) (*http.Response, error) {
        res, err := t.Transport.RoundTrip(req)
        lgr.Println("checking the response")
        // check the response
        return res, err
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度