在每个请求上使用不同的代理

时间:2017-11-15 08:38:38

标签: http go proxy

就我的理解而言,我可以为请求设置代理的唯一方法是将其分配给客户端,然后将其用于请求。但是,我也理解我应该为我的请求重用客户端。有没有办法在使用同一个客户端时为每个请求单独分配代理?或者以任何方式有效地为每个请求使用不同的代理执行请求集合?

1 个答案:

答案 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/")