mattn/go-ieproxy

Helper functions

jsmouret opened this issue · 4 comments

Hello,

Nice work :)
How do you plug FindProxyForURL in a workflow?
I'm wondering if you use something like this:

func Handler(req *http.Request) (*url.URL, error) {
	conf := GetConf()
	if conf.Static.Active {
		return http.ProxyFromEnvironment(req)
	}
	if conf.Automatic.Active {
		proxy := conf.Automatic.FindProxyForURL(req.URL.String())
		if proxy != "" {
			return url.Parse(proxy)
		}
	}
	return nil, nil
}

// Client is a proxy enabled http.Client
var Client = &http.Client{
	Transport: &http.Transport{
		Proxy: Handler,
	},
}

// Get issues a GET to the specified URL using the proxy.
func Get(url string) (*http.Response, error) {
	return Client.Get(url)
}

If yes, would it be something interesting to add to the library?

Thank you

mattn commented

@oliverpool could you please handle this issue? (if possible)

@jsmouret you raise a really good point!

Actually writing a Proxy handler is actually quite complex.

I considered at some point copy/pasting the http.ProxyFromEnvironment function (which actually checks other things and may evolve in the future).

There is also the issue of priority : if a static and an automatic configurations are available, which one should be preferred?


Maybe we could add a ProxyURL(*Request) (*url.URL, error) method to all configurations (Static, Automatic, ProxyConf) which acts like ProxyFromEnvironment.
Regarding the priority issue, a new field PreferAutomaticConf (with default to false) could solve the issue.

This would also simplify your Handler


We could also propose a change to the http lib to split http.ProxyFromEnvironment in two parts (I'm not satisfied of the name of the new function...):

func ProxyFromEnvironment(req *Request) (*url.URL, error) {
  	var proxy string
  	if req.URL.Scheme == "https" {
  		proxy = httpsProxyEnv.Get()
  	}
  	if proxy == "" {
  		proxy = httpProxyEnv.Get()
  		if proxy != "" && os.Getenv("REQUEST_METHOD") != "" {
  			return nil, errors.New("net/http: refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy")
  		}
  	}
        return ProxyRequest(proxy, req)

func ProxyRequest(proxy string, req *Request) (*url.URL, error) {
  	if proxy == "" {
  		return nil, nil
  	}
  	if !useProxy(canonicalAddr(req.URL)) {
  		return nil, nil
  	}
  	proxyURL, err := url.Parse(proxy)
  	if err != nil ||
  		(proxyURL.Scheme != "http" &&
  			proxyURL.Scheme != "https" &&
  			proxyURL.Scheme != "socks5") {
  		// proxy was bogus. Try prepending "http://" to it and
  		// see if that parses correctly. If not, we fall
  		// through and complain about the original one.
  		if proxyURL, err := url.Parse("http://" + proxy); err == nil {
  			return proxyURL, nil
  		}
  
  	}
  	if err != nil {
  		return nil, fmt.Errorf("invalid proxy address %q: %v", proxy, err)
  	}
  	return proxyURL, nil
  }

Currently adding the ProxyURL(*Request) (*url.URL, error) (and removing FindProxyForURL ?) has my preference !

What do you think about it?

This has been addressed by #10.

See GetProxyFunc

// Client is a proxy enabled http.Client
var Client = &http.Client{
	Transport: &http.Transport{
		Proxy: ieproxy.GetProxyFunc(),
	},
}

Awesome :)