소스 검색

Merge branch 'master' of https://github.com/aliyun/aliyun-oss-go-sdk

鸣镝 9 년 전
부모
커밋
fdc47f84ab
5개의 변경된 파일154개의 추가작업 그리고 127개의 파일을 삭제
  1. 0 100
      doc/index.json
  2. 34 3
      oss/client.go
  3. 53 7
      oss/client_test.go
  4. 11 0
      oss/conf.go
  5. 56 17
      oss/conn.go

+ 0 - 100
doc/index.json

@@ -1,100 +0,0 @@
-[
-  {
-    "key": "安装",
-    "name_en": "install",
-    "name_cn": "安装",
-    "tag": [],
-    "isFolder": false
-  },
-  {
-    "key": "快速开始",
-    "name_en": "getting-started",
-    "name_cn": "快速开始",
-    "tag": [],
-    "isFolder": false
-  },
-  {
-    "key": "管理Bucket",
-    "name_en": "bucket-management",
-    "name_cn": "管理Bucket",
-    "tag": [],
-    "isFolder": false
-  },
-  {
-    "key": "上传文件",
-    "name_en": "put-object",
-    "name_cn": "上传文件",
-    "tag": [],
-    "isFolder": false
-  },
-  {
-    "key": "下载文件",
-    "name_en": "get-object",
-    "name_cn": "下载文件",
-    "tag": [],
-    "isFolder": false
-  },
-  {
-    "key": "管理文件",
-    "name_en": "object-management",
-    "name_cn": "管理文件",
-    "tag": [],
-    "isFolder": false
-  },
-  {
-    "key": "自定义域名绑定",
-    "name_en": "custom-domain",
-    "name_cn": "自定义域名绑定",
-    "tag": [],
-    "isFolder": false
-  },
-  {
-    "key": "设置访问权限",
-    "name_en": "acl",
-    "name_cn": "设置访问权限",
-    "tag": [],
-    "isFolder": false
-  },
-  {
-    "key": "管理生命周期",
-    "name_en": "lifecycle-management",
-    "name_cn": "管理生命周期",
-    "tag": [],
-    "isFolder": false
-  },
-  {
-    "key": "设置访问日志",
-    "name_en": "object-logging",
-    "name_cn": "设置访问日志",
-    "tag": [],
-    "isFolder": false
-  },
-  {
-    "key": "静态网站托管",
-    "name_en": "website-hosting",
-    "name_cn": "静态网站托管",
-    "tag": [],
-    "isFolder": false
-  },
-  {
-    "key": "设置防盗链",
-    "name_en": "anti-hotlinking",
-    "name_cn": "设置防盗链",
-    "tag": [],
-    "isFolder": false
-  },
-  {
-    "key": "设置跨域资源共享",
-    "name_en": "cors",
-    "name_cn": "设置跨域资源共享",
-    "tag": [],
-    "isFolder": false
-  },
-  {
-    "key": "错误",
-    "name_en": "error",
-    "name_cn": "错误",
-    "tag": [],
-    "isFolder": false
-  }
-]

+ 34 - 3
oss/client.go

@@ -45,7 +45,7 @@ func New(endpoint, accessKeyID, accessKeySecret string, options ...ClientOption)
 	config.AccessKeySecret = accessKeySecret
 
 	url := &urlMaker{}
-	url.Init(config.Endpoint, config.IsCname)
+	url.Init(config.Endpoint, config.IsCname, config.IsUseProxy)
 	conn := &Conn{config, url}
 
 	client := &Client{
@@ -626,7 +626,7 @@ func (client Client) GetBucketInfo(bucketName string) (GetBucketInfoResult, erro
 func UseCname(isUseCname bool) ClientOption {
 	return func(client *Client) {
 		client.Config.IsCname = isUseCname
-		client.Conn.url.Init(client.Config.Endpoint, client.Config.IsCname)
+		client.Conn.url.Init(client.Config.Endpoint, client.Config.IsCname, client.Config.IsUseProxy)
 	}
 }
 
@@ -661,7 +661,7 @@ func SecurityToken(token string) ClientOption {
 }
 
 //
-// EnableMD5 上传时是否启用MD5校验,默认启用。
+// EnableMD5 是否启用MD5校验,默认启用。
 //
 // isEnableMD5 true启用MD5校验,false不启用MD5校验,默认true
 //
@@ -671,6 +671,37 @@ func EnableMD5(isEnableMD5 bool) ClientOption {
 	}
 }
 
+//
+// Proxy 设置代理服务器,默认不使用代理。
+//
+// proxyHost 代理服务器地址,格式是host或host:port
+//
+func Proxy(proxyHost string) ClientOption {
+	return func(client *Client) {
+		client.Config.IsUseProxy = true
+		client.Config.ProxyHost = proxyHost
+		client.Conn.url.Init(client.Config.Endpoint, client.Config.IsCname, client.Config.IsUseProxy)
+	}
+}
+
+//
+// AuthProxy 设置需要认证的代理服务器,默认不使用代理。
+//
+// proxyHost 代理服务器地址,格式是host或host:port
+// proxyUser 代理服务器认证的用户名
+// proxyPassword 代理服务器认证的用户密码
+//
+func AuthProxy(proxyHost, proxyUser, proxyPassword string) ClientOption {
+	return func(client *Client) {
+		client.Config.IsUseProxy = true
+		client.Config.ProxyHost = proxyHost
+		client.Config.IsAuthProxy = true
+		client.Config.ProxyUser = proxyUser
+		client.Config.ProxyPassword = proxyPassword
+		client.Conn.url.Init(client.Config.Endpoint, client.Config.IsCname, client.Config.IsUseProxy)
+	}
+}
+
 // Private
 func (client Client) do(method, bucketName, urlParams, subResource string,
 	headers map[string]string, data io.Reader) (*Response, error) {

+ 53 - 7
oss/client_test.go

@@ -7,8 +7,8 @@ package oss
 import (
 	"log"
 	"os"
-	"testing"
 	"strings"
+	"testing"
 	"time"
 
 	. "gopkg.in/check.v1"
@@ -19,7 +19,7 @@ func Test(t *testing.T) {
 	TestingT(t)
 }
 
-type OssClientSuite struct {}
+type OssClientSuite struct{}
 
 var _ = Suite(&OssClientSuite{})
 
@@ -29,12 +29,13 @@ const (
 	accessID         = "<testAccessID>"
 	accessKey        = "<testAccessKey>"
 	bucketNamePrefix = "go-sdk-test-"
+	proxyHost        = "<http://testProxy>"
 )
 
 var (
-	logPath = "go_sdk_test_" + time.Now().Format("20060102_150405") + ".log"
+	logPath        = "go_sdk_test_" + time.Now().Format("20060102_150405") + ".log"
 	testLogFile, _ = os.OpenFile(logPath, os.O_RDWR|os.O_CREATE, 0664)
-	testLogger = log.New(testLogFile, "", log.Ldate|log.Ltime|log.Lshortfile)
+	testLogger     = log.New(testLogFile, "", log.Ldate|log.Ltime|log.Lshortfile)
 )
 
 // Run once when the suite starts running
@@ -1111,7 +1112,7 @@ func (s *OssClientSuite) TestGetBucketInfo(c *C) {
 	c.Assert(strings.HasSuffix(res.BucketInfo.ExtranetEndpoint, ".com"), Equals, true)
 	c.Assert(strings.HasSuffix(res.BucketInfo.IntranetEndpoint, ".com"), Equals, true)
 	c.Assert(res.BucketInfo.CreationDate, NotNil)
-	
+
 	err = client.DeleteBucket(bucketNameTest)
 	c.Assert(err, IsNil)
 }
@@ -1223,10 +1224,10 @@ func (s *OssClientSuite) TestClientOption(c *C) {
 	var bucketNameTest = bucketNamePrefix + "tco"
 
 	client, err := New(endpoint, accessID, accessKey, UseCname(true),
-		Timeout(11, 12), SecurityToken("token"))
+		Timeout(11, 12), SecurityToken("token"), Proxy(proxyHost))
 	c.Assert(err, IsNil)
 
-	// Create
+	// Create Bucket timeout
 	err = client.CreateBucket(bucketNameTest)
 	c.Assert(err, NotNil)
 
@@ -1237,6 +1238,51 @@ func (s *OssClientSuite) TestClientOption(c *C) {
 
 	c.Assert(client.Conn.config.SecurityToken, Equals, "token")
 	c.Assert(client.Conn.config.IsCname, Equals, true)
+
+	c.Assert(client.Conn.config.IsUseProxy, Equals, true)
+	c.Assert(client.Config.ProxyHost, Equals, proxyHost)
+
+	client, err = New(endpoint, accessID, accessKey, AuthProxy(proxyHost, "user", "passwd"))
+
+	c.Assert(client.Conn.config.IsUseProxy, Equals, true)
+	c.Assert(client.Config.ProxyHost, Equals, proxyHost)
+	c.Assert(client.Conn.config.IsAuthProxy, Equals, true)
+	c.Assert(client.Conn.config.ProxyUser, Equals, "user")
+	c.Assert(client.Conn.config.ProxyPassword, Equals, "passwd")
+}
+
+func (s *OssClientSuite) TestProxy(c *C) {
+	bucketNameTest := bucketNamePrefix + "tp"
+	objectName := "体育/奥运/首金"
+	objectValue := "大江东去,浪淘尽,千古风流人物。 故垒西边,人道是、三国周郎赤壁。"
+
+	client, err := New(endpoint, accessID, accessKey, Proxy(proxyHost))
+
+	// Create bucket
+	err = client.CreateBucket(bucketNameTest)
+	c.Assert(err, IsNil)
+
+	// Get bucket info
+	_, err = client.GetBucketInfo(bucketNameTest)
+	c.Assert(err, IsNil)
+
+	bucket, err := client.Bucket(bucketNameTest)
+
+	// Put object
+	err = bucket.PutObject(objectName, strings.NewReader(objectValue))
+	c.Assert(err, IsNil)
+
+	// Get Object
+	_, err = bucket.GetObject(objectName)
+	c.Assert(err, IsNil)
+
+	// Delete Object
+	err = bucket.DeleteObject(objectName)
+	c.Assert(err, IsNil)
+
+	// Delete bucket
+	err = client.DeleteBucket(bucketNameTest)
+	c.Assert(err, IsNil)
 }
 
 // private

+ 11 - 0
oss/conf.go

@@ -25,6 +25,11 @@ type Config struct {
 	IsCname         bool        // Endpoint是否是CNAME
 	HTTPTimeout     HTTPTimeout // HTTP的超时时间设置
 	IsEnableMD5     bool        // 上传数据时是否启用MD5校验
+	IsUseProxy      bool        // 是否使用代理
+	ProxyHost       string      // 代理服务器地址
+	IsAuthProxy     bool        // 代理服务器是否使用用户认证
+	ProxyUser       string      // 代理服务器认证用户名
+	ProxyPassword   string      // 代理服务器认证密码
 }
 
 // 获取默认配置
@@ -47,5 +52,11 @@ func getDefaultOssConfig() *Config {
 	config.HTTPTimeout.HeaderTimeout = time.Second * 60    // 60s
 	config.HTTPTimeout.LongTimeout = time.Second * 300     // 300s
 
+	config.IsUseProxy = false
+	config.ProxyHost = ""
+	config.IsAuthProxy = false
+	config.ProxyUser = ""
+	config.ProxyPassword = ""
+
 	return &config
 }

+ 56 - 17
oss/conn.go

@@ -42,7 +42,9 @@ func (conn Conn) doRequest(method string, uri *url.URL, canonicalizedResource st
 	headers map[string]string, data io.Reader) (*Response, error) {
 	httpTimeOut := conn.config.HTTPTimeout
 	method = strings.ToUpper(method)
-	uri.Opaque = uri.Path
+	if !conn.config.IsUseProxy {
+		uri.Opaque = uri.Path
+	}
 	req := &http.Request{
 		Method:     method,
 		URL:        uri,
@@ -70,17 +72,48 @@ func (conn Conn) doRequest(method string, uri *url.URL, canonicalizedResource st
 
 	conn.signHeader(req, canonicalizedResource)
 
-	timeoutClient := &http.Client{Transport: &http.Transport{
-		Dial: func(netw, addr string) (net.Conn, error) {
-			conn, err := net.DialTimeout(netw, addr, httpTimeOut.ConnectTimeout)
-			if err != nil {
-				return nil, err
-			}
-			return newTimeoutConn(conn, httpTimeOut.ReadWriteTimeout, httpTimeOut.LongTimeout), nil
-		},
-		ResponseHeaderTimeout: httpTimeOut.HeaderTimeout,
-		MaxIdleConnsPerHost:   2000,
-	}}
+	var transport *http.Transport
+	if conn.config.IsUseProxy {
+		// proxy
+		proxyURL, err := url.Parse(conn.config.ProxyHost)
+		if err != nil {
+			return nil, err
+		}
+
+		transport = &http.Transport{
+			Proxy: http.ProxyURL(proxyURL),
+			Dial: func(netw, addr string) (net.Conn, error) {
+				conn, err := net.DialTimeout(netw, addr, httpTimeOut.ConnectTimeout)
+				if err != nil {
+					return nil, err
+				}
+				return newTimeoutConn(conn, httpTimeOut.ReadWriteTimeout, httpTimeOut.LongTimeout), nil
+			},
+			ResponseHeaderTimeout: httpTimeOut.HeaderTimeout,
+			MaxIdleConnsPerHost:   2000,
+		}
+
+		if conn.config.IsAuthProxy {
+			auth := conn.config.ProxyUser + ":" + conn.config.ProxyPassword
+			basic := "Basic " + base64.StdEncoding.EncodeToString([]byte(auth))
+			req.Header.Set("Proxy-Authorization", basic)
+		}
+	} else {
+		// no proxy
+		transport = &http.Transport{
+			Dial: func(netw, addr string) (net.Conn, error) {
+				conn, err := net.DialTimeout(netw, addr, httpTimeOut.ConnectTimeout)
+				if err != nil {
+					return nil, err
+				}
+				return newTimeoutConn(conn, httpTimeOut.ReadWriteTimeout, httpTimeOut.LongTimeout), nil
+			},
+			ResponseHeaderTimeout: httpTimeOut.HeaderTimeout,
+			MaxIdleConnsPerHost:   2000,
+		}
+	}
+
+	timeoutClient := &http.Client{Transport: transport}
 
 	resp, err := timeoutClient.Do(req)
 	if err != nil {
@@ -260,13 +293,14 @@ const (
 )
 
 type urlMaker struct {
-	Scheme string // http or https
-	NetLoc string // host or ip
-	Type   int    // 1 CNAME 2 IP 3 ALIYUN
+	Scheme  string // http or https
+	NetLoc  string // host or ip
+	Type    int    // 1 CNAME 2 IP 3 ALIYUN
+	IsProxy bool   // proxy
 }
 
 // Parse endpoint
-func (um *urlMaker) Init(endpoint string, isCname bool) {
+func (um *urlMaker) Init(endpoint string, isCname bool, isProxy bool) {
 	if strings.HasPrefix(endpoint, "http://") {
 		um.Scheme = "http"
 		um.NetLoc = endpoint[len("http://"):]
@@ -290,13 +324,18 @@ func (um *urlMaker) Init(endpoint string, isCname bool) {
 	} else {
 		um.Type = urlTypeAliyun
 	}
+	um.IsProxy = isProxy
 }
 
 // Build URL
 func (um urlMaker) getURL(bucket, object, params string) *url.URL {
 	var host = ""
 	var path = ""
-	object = url.QueryEscape(object)
+
+	if !um.IsProxy {
+		object = url.QueryEscape(object)
+	}
+
 	if um.Type == urlTypeCname {
 		host = um.NetLoc
 		path = "/" + object