func proxyFunc(req *http.Request) (*url.URL, error) {
	httpURLStr := req.Context().Value("http")    
	httpsURLStr := req.Context().Value("https")  
	envProxyOnce.Do(func() {
		envProxyFuncValue = httpproxy.FromEnvironment().ProxyFunc()
	})
	if req.URL.Scheme == "http" {  
		if httpURLStr != nil {
			httpURL, err := url.Parse(httpURLStr.(string))
			if err != nil {
				return nil, WrapErr(err, "HTTP Proxy error, please check proxy url")
			}
			return httpURL, nil
		}
	} else if req.URL.Scheme == "https" {  
		if httpsURLStr != nil {
			httpsURL, err := url.Parse(httpsURLStr.(string))
			if err != nil {
				return nil, WrapErr(err, "HTTPS Proxy error, please check proxy url")
			}
			return httpsURL, nil
		}
	}
	return envProxyFuncValue(req.URL)
}
proxyFunc get proxy from request context.
If there is no proxy set, use default proxy from environment.
package direwolf
import (
	"net"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"sync"
	"time"
	"golang.org/x/net/http/httpproxy"
	"golang.org/x/net/publicsuffix"
)
type Session struct {
	client    *http.Client
	transport *http.Transport
	Headers   http.Header
	Proxy     *Proxy
	Timeout   int
}
func NewSession(options ...*SessionOptions) *Session {
	var sessionOptions *SessionOptions
	if len(options) > 0 {
		sessionOptions = options[0]
	} else {
		sessionOptions = DefaultSessionOptions()
	}
	trans := &http.Transport{
		DialContext: (&net.Dialer{
			Timeout:   sessionOptions.DialTimeout,
			KeepAlive: sessionOptions.DialKeepAlive,
		}).DialContext,
		MaxIdleConns:          sessionOptions.MaxIdleConns,
		MaxIdleConnsPerHost:   sessionOptions.MaxIdleConnsPerHost,
		MaxConnsPerHost:       sessionOptions.MaxConnsPerHost,
		IdleConnTimeout:       sessionOptions.IdleConnTimeout,
		TLSHandshakeTimeout:   sessionOptions.TLSHandshakeTimeout,
		ExpectContinueTimeout: sessionOptions.ExpectContinueTimeout,
		Proxy:                 proxyFunc,
	}
	if sessionOptions.DisableDialKeepAlives {
		trans.DisableKeepAlives = true
	}
	client := &http.Client{
		Transport:     trans,
		CheckRedirect: redirectFunc,
	}
	if sessionOptions.DisableCookieJar == false {
		cookieJarOptions := cookiejar.Options{
			PublicSuffixList: publicsuffix.List,
		}
		jar, err := cookiejar.New(&cookieJarOptions)
		if err != nil {
			return nil
		}
		client.Jar = jar
	}
	headers := http.Header{}
	headers.Add("User-Agent", "direwolf - winter is coming")
	return &Session{
		client:    client,
		transport: trans,
		Headers:   headers,
	}
}
func (session *Session) Send(req *Request) (*Response, error) {
	resp, err := send(session, req)
	if err != nil {
		return nil, WrapErr(err, "session send failed")
	}
	return resp, nil
}
func (session *Session) Get(URL string, args ...RequestOption) (*Response, error) {
	req, err := NewRequest("GET", URL, args...)
	if err != nil {
		return nil, err
	}
	resp, err := session.Send(req)
	if err != nil {
		return nil, err
	}
	return resp, nil
}
func (session *Session) Post(URL string, args ...RequestOption) (*Response, error) {
	req, err := NewRequest("POST", URL, args...)
	if err != nil {
		return nil, err
	}
	resp, err := session.Send(req)
	if err != nil {
		return nil, err
	}
	return resp, nil
}
func (session *Session) Head(URL string, args ...RequestOption) (*Response, error) {
	req, err := NewRequest("HEAD", URL, args...)
	if err != nil {
		return nil, err
	}
	resp, err := session.Send(req)
	if err != nil {
		return nil, err
	}
	return resp, nil
}
func (session *Session) Put(URL string, args ...RequestOption) (*Response, error) {
	req, err := NewRequest("PUT", URL, args...)
	if err != nil {
		return nil, err
	}
	resp, err := session.Send(req)
	if err != nil {
		return nil, err
	}
	return resp, nil
}
func (session *Session) Patch(URL string, args ...RequestOption) (*Response, error) {
	req, err := NewRequest("PATCH", URL, args...)
	if err != nil {
		return nil, err
	}
	resp, err := session.Send(req)
	if err != nil {
		return nil, err
	}
	return resp, nil
}
func (session *Session) Delete(URL string, args ...RequestOption) (*Response, error) {
	req, err := NewRequest("DELETE", URL, args...)
	if err != nil {
		return nil, err
	}
	resp, err := session.Send(req)
	if err != nil {
		return nil, err
	}
	return resp, nil
}
func (session *Session) Cookies(URL string) Cookies {
	if session.client.Jar == nil {
		return nil
	}
	parsedURL, err := url.Parse(URL)
	if err != nil {
		return nil
	}
	return session.client.Jar.Cookies(parsedURL)
}
func (session *Session) SetCookies(URL string, cookies Cookies) {
	if session.client.Jar == nil {
		return
	}
	parsedURL, err := url.Parse(URL)
	if err != nil {
		return
	}
	session.client.Jar.SetCookies(parsedURL, cookies)
}
type SessionOptions struct {
	DialTimeout time.Duration
	DialKeepAlive time.Duration
	MaxConnsPerHost int
	MaxIdleConns int
	MaxIdleConnsPerHost int
	IdleConnTimeout time.Duration
	TLSHandshakeTimeout time.Duration
	ExpectContinueTimeout time.Duration
	DisableCookieJar bool
	DisableDialKeepAlives bool
}
func DefaultSessionOptions() *SessionOptions {
	return &SessionOptions{
		DialTimeout:           30 * time.Second,
		DialKeepAlive:         30 * time.Second,
		MaxConnsPerHost:       0,
		MaxIdleConns:          100,
		MaxIdleConnsPerHost:   2,
		IdleConnTimeout:       90 * time.Second,
		TLSHandshakeTimeout:   10 * time.Second,
		ExpectContinueTimeout: 1 * time.Second,
		DisableCookieJar:      false,
		DisableDialKeepAlives: false,
	}
}
var (
	envProxyOnce      sync.Once
	envProxyFuncValue func(*url.URL) (*url.URL, error)
)