就我的理解而言,我可以为请求设置代理的唯一方法是将其分配给客户端,然后将其用于请求。但是,我也理解我应该为我的请求重用客户端。有没有办法在使用同一个客户端时为每个请求单独分配代理?或者以任何方式有效地为每个请求使用不同的代理执行请求集合?
答案 0 :(得分:1)
创建http.Client并不是那么昂贵 - 它只是一个可以为每个请求完成的结构分配。
您应该自己创建http.Client和传输对象,并在那里直接设置代理。
proxyUrl, err := url.Parse("http://127.0.0.1:123")
if err != nil {
panic(err)
}
myClient := &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxyUrl)}}
myClient.Get("http://www.google.com/")
Tere是使用不同代理的同一客户端的另一个可能性:
来自第一个例子的http.ProxyURL调用是函数:// ProxyURL returns a proxy function (for use in a Transport)
// that always returns the same URL.
func ProxyURL(fixedURL *url.URL) func(*Request) (*url.URL, error) {
return func(*Request) (*url.URL, error) {
return fixedURL, nil
}
}
您可以扩展它并根据请求中的信息选择代理或实现其他逻辑。
UPD :这里是如何将ProxyUrl与一个客户端一起使用的实现。但过度改变上下文与创建客户端的开销相当。我会使用第一个场景。
//我们必须编写自己的Get(或其他一些)请求,并添加一些信息,这是一个代理请求。您可以通过请求的上下文来完成。
func GetWithProxy(c *http.Client,proxyUrl *url.URL, url string) (resp *http.Response, err error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
if proxyUrl != nil {
req = req.WithContext(context.WithValue(context.Background(),"proxy",proxyUrl))
}
return c.Do(req)
}
//组织可以使用此信息的客户端:
proxyUrl, err := url.Parse("http://127.0.0.1:123")
if err != nil {
panic(err)
}
myClient := &http.Client{Transport: &http.Transport{Proxy: func(req *http.Request) (*url.URL, error) {
currentProxy,_ := req.Context().Value("proxy").(*url.URL)
return currentProxy, nil
}}}
使用它:
GetWithProxy(myClient,nil,"http://www.google.com/")
GetWithProxy(myClient,proxyUrl,"http://www.google.com/")