瀏覽代碼

fix http proxy

wenzuochao 6 年之前
父節點
當前提交
9faeecb97b
共有 5 個文件被更改,包括 173 次插入49 次删除
  1. 10 8
      README.md
  2. 10 8
      README_zh.md
  3. 2 2
      integration/core_test.go
  4. 69 12
      sdk/client.go
  5. 82 19
      sdk/client_test.go

+ 10 - 8
README.md

@@ -118,16 +118,18 @@ isInsecure := client.GetHTTPSInsecure()               // Get client HTTPSInsecur
 
 
 ## HTTP Proxy
 ## HTTP Proxy
 
 
-If you want to use http proxy or https proxy, you can set environment variables `HTTP_PROXY` or `HTTPS_PROXY`, or you can configure client with config.
+If you want to use http proxy,  https proxy or no proxy, you can set environment variables `HTTP_PROXY`, `HTTPS_PROXY` or `NO_PROXY`, or you can set them by client.
 
 
 ```go
 ```go
-rawurl, _ := url.Parse("http://117.215.227.125:8888") //You should replace the IP with you want
-httpTransport := http.Transport{
-    Proxy:  http.ProxyURL(rawurl)
-}
-config := sdk.NewConfig()
-            .WithHttpTransport(&httpTransport)
-ecsClient, err := ecs.NewClientWithOptions(config)
+// client proxy has a high priority than environment variables.
+client.SetHttpProxy("http://127.0.0.1:8080")   // Set Http Proxy.
+client.GetHttpProxy()                          // Get Http Proxy.
+
+client.SetHttpsProxy("https://127.0.0.1:8080")   // Set Https Proxy.
+client.GetHttpsProxy()                           // Get Https Proxy.
+
+client.SetNoProxy("127.0.0.1,localhost")     // Set No Proxy.
+client.GetNoProxy()                          // Get No Proxy.
 ```
 ```
 
 
 ## Keep-alive
 ## Keep-alive

+ 10 - 8
README_zh.md

@@ -109,16 +109,18 @@ isInsecure := client.GetHTTPSInsecure()               // 获取客户端 HTTPSIn
 
 
 ## HTTP 代理
 ## HTTP 代理
 
 
-如果您想使用 http 代理或 https 代理,您可以设置环境变量 `HTTP_PROXY` 或者 `HTTPS_PROXY`,您也可以使用 config 配置客户端
+如果您想使用 http 代理, https 代理或者代理白名单,您可以设置环境变量 `HTTP_PROXY` 或者 `HTTPS_PROXY`或者 `NO_PROXY`,您也可以通过客户端来配置
 
 
 ```go
 ```go
-rawurl, _ := url.Parse("http://117.215.227.125:8888") //You should replace the IP with you want
-httpTransport := http.Transport{
-    Proxy:  http.ProxyURL(rawurl)
-}
-config := sdk.NewConfig()
-            .WithHttpTransport(&httpTransport)
-ecsClient, err := ecs.NewClientWithOptions(config)
+// 客户端设置代理优先级比环境变量高
+client.SetHttpProxy("http://127.0.0.1:8080")   // 设置 Http 代理
+client.GetHttpProxy()                          // 获取 Http 代理.
+
+client.SetHttpsProxy("https://127.0.0.1:8080")   // 设置 Https 代理.
+client.GetHttpsProxy()                           // 获取 Https 代理.
+
+client.SetNoProxy("127.0.0.1,localhost")     // 设置代理白名单.
+client.GetNoProxy()                          // 获取代理白名单
 ```
 ```
 
 
 ## Keep-alive
 ## Keep-alive

+ 2 - 2
integration/core_test.go

@@ -262,13 +262,13 @@ func handlerFake(w http.ResponseWriter, r *http.Request) {
 	return
 	return
 }
 }
 
 
-func handlerFakeServer() (server *httptest.Server){
+func handlerFakeServer() (server *httptest.Server) {
 	server = httptest.NewServer(http.HandlerFunc(handlerFake))
 	server = httptest.NewServer(http.HandlerFunc(handlerFake))
 
 
 	return server
 	return server
 }
 }
 
 
-func handlerTrueServer() (server *httptest.Server){
+func handlerTrueServer() (server *httptest.Server) {
 	server = httptest.NewServer(http.HandlerFunc(handlerTrue))
 	server = httptest.NewServer(http.HandlerFunc(handlerTrue))
 
 
 	return server
 	return server

+ 69 - 12
sdk/client.go

@@ -61,6 +61,9 @@ type Client struct {
 	isInsecure     bool
 	isInsecure     bool
 	regionId       string
 	regionId       string
 	config         *Config
 	config         *Config
+	httpProxy      *string
+	httpsProxy     *string
+	noProxy        *string
 	userAgent      map[string]string
 	userAgent      map[string]string
 	signer         auth.Signer
 	signer         auth.Signer
 	httpClient     *http.Client
 	httpClient     *http.Client
@@ -86,6 +89,30 @@ func (client *Client) GetHTTPSInsecure() bool {
 	return client.isInsecure
 	return client.isInsecure
 }
 }
 
 
+func (client *Client) SetHttpsProxy(httpsProxy string) {
+	client.httpsProxy = &httpsProxy
+}
+
+func (client *Client) GetHttpsProxy() *string {
+	return client.httpsProxy
+}
+
+func (client *Client) SetHttpProxy(httpProxy string) {
+	client.httpProxy = &httpProxy
+}
+
+func (client *Client) GetHttpProxy() *string {
+	return client.httpProxy
+}
+
+func (client *Client) SetNoProxy(noProxy string) {
+	client.noProxy = &noProxy
+}
+
+func (client *Client) GetNoProxy() *string {
+	return client.noProxy
+}
+
 // InitWithProviderChain will get credential from the providerChain,
 // InitWithProviderChain will get credential from the providerChain,
 // the RsaKeyPairCredential Only applicable to regionID `ap-northeast-1`,
 // the RsaKeyPairCredential Only applicable to regionID `ap-northeast-1`,
 // if your providerChain may return a credential type with RsaKeyPairCredential,
 // if your providerChain may return a credential type with RsaKeyPairCredential,
@@ -139,25 +166,43 @@ func (client *Client) GetConnectTimeout() time.Duration {
 	return client.connectTimeout
 	return client.connectTimeout
 }
 }
 
 
-func getHttpProxy(scheme string) *url.URL {
+func (client *Client) getHttpProxy(scheme string) (*url.URL, error) {
 	var proxy *url.URL
 	var proxy *url.URL
+	var err error
 	if scheme == "https" {
 	if scheme == "https" {
-		if rawurl := os.Getenv("HTTPS_PROXY"); rawurl != "" {
-			proxy, _ = url.Parse(rawurl)
-		}
-		if rawurl := os.Getenv("https_proxy"); rawurl != "" && proxy == nil {
-			proxy, _ = url.Parse(rawurl)
+		if client.GetHttpsProxy() != nil {
+			proxy, err = url.Parse(*client.httpsProxy)
+		} else if rawurl := os.Getenv("HTTPS_PROXY"); rawurl != "" {
+			proxy, err = url.Parse(rawurl)
+		} else if rawurl := os.Getenv("https_proxy"); rawurl != "" {
+			proxy, err = url.Parse(rawurl)
 		}
 		}
 	} else {
 	} else {
-		if rawurl := os.Getenv("HTTP_PROXY"); rawurl != "" {
-			proxy, _ = url.Parse(rawurl)
+		if client.GetHttpProxy() != nil {
+			proxy, err = url.Parse(*client.httpProxy)
+		}
+		if rawurl := os.Getenv("HTTP_PROXY"); rawurl != "" && proxy == nil {
+			proxy, err = url.Parse(rawurl)
 		}
 		}
 		if rawurl := os.Getenv("http_proxy"); rawurl != "" && proxy == nil {
 		if rawurl := os.Getenv("http_proxy"); rawurl != "" && proxy == nil {
-			proxy, _ = url.Parse(rawurl)
+			proxy, err = url.Parse(rawurl)
 		}
 		}
 	}
 	}
 
 
-	return proxy
+	return proxy, err
+}
+
+func (client *Client) getNoProxy(scheme string) []string {
+	var urls []string
+	if client.GetNoProxy() != nil {
+		urls = strings.Split(*client.noProxy, ",")
+	} else if rawurl := os.Getenv("NO_PROXY"); rawurl != "" {
+		urls = strings.Split(rawurl, ",")
+	} else if rawurl := os.Getenv("no_proxy"); rawurl != "" {
+		urls = strings.Split(rawurl, ",")
+	}
+
+	return urls
 }
 }
 
 
 // EnableAsync enable the async task queue
 // EnableAsync enable the async task queue
@@ -406,7 +451,19 @@ func (client *Client) DoActionWithSigner(request requests.AcsRequest, response r
 		return
 		return
 	}
 	}
 	client.setTimeout(request)
 	client.setTimeout(request)
-	proxy := getHttpProxy(httpRequest.URL.Scheme)
+	proxy, err := client.getHttpProxy(httpRequest.URL.Scheme)
+	if err != nil {
+		return err
+	}
+	noProxy := client.getNoProxy(httpRequest.URL.Scheme)
+
+	var flag bool
+	for _, value := range noProxy {
+		if value == httpRequest.Host {
+			flag = true
+			break
+		}
+	}
 
 
 	// Set whether to ignore certificate validation.
 	// Set whether to ignore certificate validation.
 	// Default InsecureSkipVerify is false.
 	// Default InsecureSkipVerify is false.
@@ -414,7 +471,7 @@ func (client *Client) DoActionWithSigner(request requests.AcsRequest, response r
 		trans.TLSClientConfig = &tls.Config{
 		trans.TLSClientConfig = &tls.Config{
 			InsecureSkipVerify: client.getHTTPSInsecure(request),
 			InsecureSkipVerify: client.getHTTPSInsecure(request),
 		}
 		}
-		if proxy != nil {
+		if proxy != nil && !flag {
 			trans.Proxy = http.ProxyURL(proxy)
 			trans.Proxy = http.ProxyURL(proxy)
 		}
 		}
 		client.httpClient.Transport = trans
 		client.httpClient.Transport = trans

+ 82 - 19
sdk/client_test.go

@@ -139,7 +139,7 @@ func mockResponse(statusCode int, content string, mockerr error) (res *http.Resp
 	return
 	return
 }
 }
 
 
-func Test_DoAction(t *testing.T) {
+func Test_DoActionWithProxy(t *testing.T) {
 	client, err := NewClientWithAccessKey("regionid", "acesskeyid", "accesskeysecret")
 	client, err := NewClientWithAccessKey("regionid", "acesskeyid", "accesskeysecret")
 	assert.Nil(t, err)
 	assert.Nil(t, err)
 	assert.NotNil(t, client)
 	assert.NotNil(t, client)
@@ -165,21 +165,42 @@ func Test_DoAction(t *testing.T) {
 	assert.Equal(t, 200, response.GetHttpStatus())
 	assert.Equal(t, 200, response.GetHttpStatus())
 	assert.Equal(t, "", response.GetHttpContentString())
 	assert.Equal(t, "", response.GetHttpContentString())
 
 
-	originEnv := os.Getenv("https_proxy")
+	// Test when scheme is http, only http proxy is valid.
+	envHttpsProxy := os.Getenv("https_proxy")
 	os.Setenv("https_proxy", "https://127.0.0.1:9000")
 	os.Setenv("https_proxy", "https://127.0.0.1:9000")
 	err = client.DoAction(request, response)
 	err = client.DoAction(request, response)
 	assert.Nil(t, err)
 	assert.Nil(t, err)
-	assert.Nil(t, client.config.HttpTransport)
+	trans, _ := client.httpClient.Transport.(*http.Transport)
+	assert.Nil(t, trans.Proxy)
 
 
-	originEnv1 := os.Getenv("http_proxy")
+	// Test when host is in no_proxy, proxy is invalid
+	envNoProxy := os.Getenv("no_proxy")
+	os.Setenv("no_proxy", "ecs.aliyuncs.com")
+	envHttpProxy := os.Getenv("http_proxy")
 	os.Setenv("http_proxy", "http://127.0.0.1:8888")
 	os.Setenv("http_proxy", "http://127.0.0.1:8888")
 	err = client.DoAction(request, response)
 	err = client.DoAction(request, response)
 	assert.Nil(t, err)
 	assert.Nil(t, err)
-	trans, _ := client.httpClient.Transport.(*http.Transport)
+	trans, _ = client.httpClient.Transport.(*http.Transport)
+	assert.Nil(t, trans.Proxy)
+
+	client.SetNoProxy("ecs.testaliyuncs.com")
+	err = client.DoAction(request, response)
+	assert.Nil(t, err)
+	trans, _ = client.httpClient.Transport.(*http.Transport)
 	url, _ := trans.Proxy(nil)
 	url, _ := trans.Proxy(nil)
 	assert.Equal(t, url.Scheme, "http")
 	assert.Equal(t, url.Scheme, "http")
 	assert.Equal(t, url.Host, "127.0.0.1:8888")
 	assert.Equal(t, url.Host, "127.0.0.1:8888")
 
 
+	// Test when setting http proxy, client has a high priority than environment variable
+	client.SetHttpProxy("http://127.0.0.1:8080")
+	err = client.DoAction(request, response)
+	assert.Nil(t, err)
+	trans, _ = client.httpClient.Transport.(*http.Transport)
+	url, _ = trans.Proxy(nil)
+	assert.Equal(t, url.Scheme, "http")
+	assert.Equal(t, url.Host, "127.0.0.1:8080")
+
+	// Test when scheme is https, only https proxy is valid
 	request.Scheme = "https"
 	request.Scheme = "https"
 	err = client.DoAction(request, response)
 	err = client.DoAction(request, response)
 	assert.Nil(t, err)
 	assert.Nil(t, err)
@@ -188,9 +209,19 @@ func Test_DoAction(t *testing.T) {
 	assert.Equal(t, url.Scheme, "https")
 	assert.Equal(t, url.Scheme, "https")
 	assert.Equal(t, url.Host, "127.0.0.1:9000")
 	assert.Equal(t, url.Host, "127.0.0.1:9000")
 
 
+	// Test when setting https proxy, client has a high priority than environment variable
+	client.SetHttpsProxy("https://127.0.0.1:6666")
+	err = client.DoAction(request, response)
+	assert.Nil(t, err)
+	trans, _ = client.httpClient.Transport.(*http.Transport)
+	url, _ = trans.Proxy(nil)
+	assert.Equal(t, url.Scheme, "https")
+	assert.Equal(t, url.Host, "127.0.0.1:6666")
+
 	client.Shutdown()
 	client.Shutdown()
-	os.Setenv("https_proxy", originEnv)
-	os.Setenv("http_proxy", originEnv1)
+	os.Setenv("https_proxy", envHttpsProxy)
+	os.Setenv("http_proxy", envHttpProxy)
+	os.Setenv("no_proxy", envNoProxy)
 	assert.Equal(t, false, client.isRunning)
 	assert.Equal(t, false, client.isRunning)
 }
 }
 
 
@@ -203,8 +234,8 @@ func Test_DoAction_HTTPSInsecure(t *testing.T) {
 	request := requests.NewCommonRequest()
 	request := requests.NewCommonRequest()
 	request.Product = "Ram"
 	request.Product = "Ram"
 	request.Version = "2015-05-01"
 	request.Version = "2015-05-01"
-	request.SetScheme("HTTPS")
 	request.ApiName = "CreateRole"
 	request.ApiName = "CreateRole"
+	request.Domain = "ecs.aliyuncs.com"
 	request.QueryParams["RegionId"] = os.Getenv("REGION_ID")
 	request.QueryParams["RegionId"] = os.Getenv("REGION_ID")
 	request.TransToAcsRequest()
 	request.TransToAcsRequest()
 	response := responses.NewCommonResponse()
 	response := responses.NewCommonResponse()
@@ -228,32 +259,64 @@ func Test_DoAction_HTTPSInsecure(t *testing.T) {
 	trans = client.httpClient.Transport.(*http.Transport)
 	trans = client.httpClient.Transport.(*http.Transport)
 	assert.Equal(t, false, trans.TLSClientConfig.InsecureSkipVerify)
 	assert.Equal(t, false, trans.TLSClientConfig.InsecureSkipVerify)
 
 
-	originEnv := os.Getenv("HTTP_PROXY")
-	os.Setenv("HTTP_PROXY", "http://127.0.0.1:9000")
+	// Test when scheme is http, only http proxy is valid.
+	envHttpsProxy := os.Getenv("HTTPS_PROXY")
+	os.Setenv("HTTPS_PROXY", "https://127.0.0.1:9000")
 	err = client.DoAction(request, response)
 	err = client.DoAction(request, response)
 	assert.Nil(t, err)
 	assert.Nil(t, err)
-	assert.Nil(t, client.config.HttpTransport)
+	trans, _ = client.httpClient.Transport.(*http.Transport)
+	assert.Nil(t, trans.Proxy)
 
 
-	originEnv1 := os.Getenv("HTTPS_PROXY")
-	os.Setenv("HTTPS_PROXY", "https://127.0.0.1:8888")
+	// Test when host is in no_proxy, proxy is invalid
+	envNoProxy := os.Getenv("NO_PROXY")
+	os.Setenv("NO_PROXY", "ecs.aliyuncs.com")
+	envHttpProxy := os.Getenv("HTTP_PROXY")
+	os.Setenv("HTTP_PROXY", "http://127.0.0.1:8888")
 	err = client.DoAction(request, response)
 	err = client.DoAction(request, response)
 	assert.Nil(t, err)
 	assert.Nil(t, err)
-	trans = client.httpClient.Transport.(*http.Transport)
+	trans, _ = client.httpClient.Transport.(*http.Transport)
+	assert.Nil(t, trans.Proxy)
+
+	client.SetNoProxy("ecs.testaliyuncs.com")
+	err = client.DoAction(request, response)
+	assert.Nil(t, err)
+	trans, _ = client.httpClient.Transport.(*http.Transport)
 	url, _ := trans.Proxy(nil)
 	url, _ := trans.Proxy(nil)
-	assert.Equal(t, url.Scheme, "https")
+	assert.Equal(t, url.Scheme, "http")
 	assert.Equal(t, url.Host, "127.0.0.1:8888")
 	assert.Equal(t, url.Host, "127.0.0.1:8888")
 
 
-	request.Scheme = "http"
+	// Test when setting http proxy, client has a high priority than environment variable
+	client.SetHttpProxy("http://127.0.0.1:8080")
 	err = client.DoAction(request, response)
 	err = client.DoAction(request, response)
 	assert.Nil(t, err)
 	assert.Nil(t, err)
-	trans = client.httpClient.Transport.(*http.Transport)
+	trans, _ = client.httpClient.Transport.(*http.Transport)
 	url, _ = trans.Proxy(nil)
 	url, _ = trans.Proxy(nil)
 	assert.Equal(t, url.Scheme, "http")
 	assert.Equal(t, url.Scheme, "http")
+	assert.Equal(t, url.Host, "127.0.0.1:8080")
+
+	// Test when scheme is https, only https proxy is valid
+	request.Scheme = "https"
+	err = client.DoAction(request, response)
+	assert.Nil(t, err)
+	trans, _ = client.httpClient.Transport.(*http.Transport)
+	url, _ = trans.Proxy(nil)
+	assert.Equal(t, url.Scheme, "https")
 	assert.Equal(t, url.Host, "127.0.0.1:9000")
 	assert.Equal(t, url.Host, "127.0.0.1:9000")
 
 
+	// Test when setting https proxy, client has a high priority than environment variable
+	client.SetHttpsProxy("https://127.0.0.1:6666")
+	err = client.DoAction(request, response)
+	assert.Nil(t, err)
+	trans, _ = client.httpClient.Transport.(*http.Transport)
+	url, _ = trans.Proxy(nil)
+	assert.Equal(t, url.Scheme, "https")
+	assert.Equal(t, url.Host, "127.0.0.1:6666")
+
 	client.Shutdown()
 	client.Shutdown()
-	os.Setenv("HTTP_PROXY", originEnv)
-	os.Setenv("HTTPS_PROXY", originEnv1)
+	os.Setenv("HTTPS_PROXY", envHttpsProxy)
+	os.Setenv("HTTP_PROXY", envHttpProxy)
+	os.Setenv("NO_PROXY", envNoProxy)
+	assert.Equal(t, false, client.isRunning)
 }
 }
 
 
 func Test_DoAction_Timeout(t *testing.T) {
 func Test_DoAction_Timeout(t *testing.T) {