Browse Source

Merge pull request #120 from aliyun/ipv6

Ipv6
fengyu 7 years ago
parent
commit
5f712e3aee
15 changed files with 292 additions and 74 deletions
  1. 10 11
      .travis.yml
  2. 56 16
      oss/bucket.go
  3. 53 2
      oss/bucket_test.go
  4. 23 30
      oss/client_test.go
  5. 15 2
      oss/conn.go
  6. 18 0
      oss/conn_test.go
  7. 6 3
      oss/const.go
  8. 8 0
      oss/model.go
  9. 15 3
      oss/multipart.go
  10. 2 2
      oss/multipart_test.go
  11. 28 2
      oss/option.go
  12. 31 1
      oss/option_test.go
  13. 8 1
      oss/progress.go
  14. 18 0
      oss/type.go
  15. 1 1
      sample/bucket_referer.go

+ 10 - 11
.travis.yml

@@ -13,16 +13,15 @@ install:
 script:
 - cd oss
 - travis_wait 30 go test -v -covermode=count -coverprofile=coverage.out -timeout=30m
-- $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci
+- "$HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci"
 env:
   global:
-  - secure: CaUx0qMkOw3GhlGJmLQBcwiLmz7U4WoQeB0MtsLpGNat6JbgP/E3E+7ZiKv17rxxLpk1yNr4pScIwm7a1gv44qmjdOk506aBK/3exVkcntMU2q1i2IhWIiNUlr9g14CR5O3xB7yaErRy/p5ILbfw8wHYqPKRBfF03p7SUmTzWsiG1BKkjwKqQrGJadXIeL45EwPCIekpE/omDFMOQvYeE8jfvSJC3mcViE3LPaSzFa5FRO4xrBpMtvdBgbAW4xXyKbQ0xjLDOwlz7lT0CwOqrKQaf8+kB7qTuvViJdRBG9PJM9jFOIOQynzuUVI8RzCp0/+DC/fGmabzP62yCzguzasp78BkzTj0TxEutfxBPKimiONjiO8yVitqG4xEB9Qh6ya4i/6ktZXfQcSKFYw8AWCHKLqzC+pEc+Um6DeeLIOWJFEO1WhZ2L1orMoH1s445xVy35KZuJBUluWZyOL3Cgwd95RXhGZ/yhfCQwkIVscHSGfavkc2RL418jTjOB+0d/fES14jkPJsQ02E8ZAIZ6hI6QBbsorHLiiSMd2CwHZG2T0n4a1d6OKWFU5ftKVDQDKGLTaWYqStCjJCxiG7g4X3uvYzEdPBDctwNFT1HxeQ9UcjNs+2VLyLXpmJCuPDf3AK5FpoCOWVa99hYhFzbzHxMpPmPTC2MT7H8orxtno=
-  - secure: F4pWK/B4irPi57wDQMKie1f8VaQBDjAFrvsX0of16+eaBaR/+DaqiRNuvYKTs1JLxgVvK3WOQNIwVcILibXr04/KrIrva44QYazfZ1eeR+TtEdy2dLzjVFHSGx/hKX0LSTXGRb2wOMsufSSGqfh8ngsr6LFp2RflGTCJ0HRyJ+p7BNL4R7rIR31STpqiV5Z2i26TMRjWDp177h5XHA1V0wOv/ZDMQUhRvdYH0uHDs76oVxZmZ3OG0EmSLSB7BuXoYT1aCkTpnZZXo39Rb5mjgObr3MWW7iCbaApNjscQ7IQ3OIUvW+RjsZ4BDVA2F88+HkC3gSnUa5Ka7gMFMAXtdC01Zxtpx8m2h18eHQOgpGcmjtU18QHDtv8AsoidgiMj9L7ZYmzo9ioXuZ9/UvBTARLJ/2+mI14VKCYintJPnWp3tXCyOrQIfr8nudpl380y0PJ+t7UMYm+PFEeUiC9MsMeFv2I6MZfx5CZBTIKr5XoIbuBC9BwFj5AIeuvXsw/qGy6gi/e/Ys5mLRTw5g9N+KFcZAsbnueoyNjlKaLP1nyrf3XJXMEuunRePpI4ABW4D+j3z2kW19f6XKNnHvBEEg2yCthk4dNouUKTL5fEv8IXXgtFoG/ADsdgDbWnOdIPmr7HcG1/VjJvhr7Yu9roSPH00J7pqABCDNebgEGxGcY=
-  - secure: dcjezQ3DMMcyFwfG64GfQVwv4C2MjnJ6Sf4jdRac9XLDXd+VS5YbjuulzOdidHdvxcDI9x6XnNb8P9lErzR7URIcnHOF5p+7kwpXPBpd4E4DZV7GBYrbHBdQTnrYjs6gWCIzdWQxCT7wju6qSF3D0XtHNG8aM2qUCMCGfI0SBewbnDXpHtmHG/Ei/0DWfQeBW+pwV5OyAfZ2r0/H1ZVA6+z15eGW9u3gCN8E73U2ly19ZLQ8mu5lNHhFM2b2AdfzT9BDmCBmRp2vaqptivt1XVQ/ugCpWXtLdNtNSV51WIjbsLrmSRCb8yoQMVFAKsEC/zZU374ZZZocBhdJ2RXD46u1iW1hmivQgg+aNFQ6rQtByyhFGcpygRd063YvYWutfL6pa0il7PHLkaOfDC33G+GNcS+zfL/XnSbF/wH+Expv+OfrgRpcamBUGO3nvJFXekqzBiDWJWP4kJDazdUYT1kWIPdjxxI4zzjw4QXsIiOKy+7ihigkRe0VjzNJUJ8FLQFCvWXmNr67dKDjrLiM8NrzYep1u6lI0dCjOJhNWfMS3wt8rGIXqD+OfLQbFQiUBJYl1QEWEzZ1EeS/i+bGLDRW85+g/BNPc2V/o0V4TJy/I0yksvOHqFU5yqmMfTnlew28dQok7OZHGOFQpXyvpTLsbEHMvad8IaTx0MJ0yKE=
-  - secure: GwuE+UMGD3NuU3f/6OPcRpT8iw8letEpfUeUIsw4C8LZsjNQAwR43oo3uCvNygjPew6+zpXqFIsggkcgFv8kC8rr6Jxq9rrxDCCQko3chKNRiB25lI10JaJ2VJxtrsHDmlC0LQgdq+RS4d8ejDCBTor1VtyCg7qqVawNYhMGv8QONs4CwiHf5ve/y9YRkNF6WH0F2iGsOJOCxcpVXo21KKCDA9M96zON2EmrElvKgfwo9OsIBaIilGqPR6lYCBvbN7KGV0wRqPTowGNfLtuOYkxBZRSkf/RJaFc10uEXEClkye5WcpumHgVfp9PoAg5Q+JYYgOInI0Gk7iyG77i9ObmkucccZ3OyFUUjRuCWBlQgzwBfKb3R8Or4VMGQ9n8bSPu50WLSRdizw2PWzFzU9p8+qFkTIJ6JCuMk8GnFiyayu8OjOxkKjKl5e5fQyynvbz397H7rnUqkl1y4mpeQI5FJz4p54cKDDuxPSqUvd15qQAhg5oDBgsWD3nj5fkI5C5tuFYBaPdgnnY7LiYqme7wu/g590HdPBfM0PCw5NquNheDuF4wn9BKlgxUUdGmCWAPmIpULIKlaPhP2VH29FXmR2oRATC3mOlorQnpXpvxaDfkNmCmMK5QcbqSRr2IJlsrApSlUhZI8FvIQwjG19MlbypGGaXxF8iNtoJfiSDE=
-  - secure: ig/rYcJNIB0nWviO+fAsv83p6yMqcA7oHQfOawZxv0fJlBUOLDUzKgvqjQZoOCNZWT7eo6VESW3cKj1DMev1jpr7H6bzsSPG7CJ+BvsWmngLBy8kkJYXUf5UGV+CyFQmAPzdaotQ699Z8Mu/X1uYCvBoMwfvyFhuStCwZSusGt+iPjUqY5qyc4zM2yOXPVLK7YdkiGodC+MlEbgOk75+D0FSU0yHZ0kKiCcOtFxDjd2/yHjd1usSNp/9m2eE7QrSNSi+62RTvBSxDEZrjmBE1jYVeg0pBFHs4DrxcKGTiGTlALkDsak/acwlFZhKS97g1DnZC/jI883t2PcrJnORrww5tZNY87/kMB3BOjOTCTHNuWvBgHgmZ0VJ5ndu1FWwCiGZsBIJIZnzp/ZygcFvalcbqKA1WlegKtyT1x9J0zqS3is4Pfnc8yFC4GVoDu4H4iF+Cb8Uo5tZrQCXYEi7HXXn4JYkohwQw4JMX4ciI/o3hkmRP8sVKn5FdqGkpkXpJ7tITd50F7mNWejxbn2kSJmEHyQuG19MQ/Bf52D71AUpZiFxMqmk513UfilozkOVgvGjhtdD7hmIgtNQ2ttzz5NukXrTshTtrE/EzA5mYLsXnhC0EXB8cLZ1kpZs72ezYNud2XgidJI63GXd/1ZSFdjlDpmv4h6vWabkDzt/sm8=
-  - secure: cn+C2FoHhBYw36yx2ObzQaeJjAEVr+cIwiFJAnRpMOusKL8v6vOQk0AGa+fJYXqCLoXJr4uliZytqos6ot4Kdkiw/XEq2fiIYi1ZG2oFyOANPjq00Rug6Ar5VpNu7XCaYcliA9bqRpGaQDDWINzyNWoI8iwmfZ58R/m27qEeoXDFNaiAZWIM3ZPvZTkKE+8FEepBTotBIRKyf7Rs7MKjWZqOxeg2cSRap6F8SvsC79CyPEu28NL+uRSxlu4EfgfvLEis6zuFxk68PqyQUo5BDiqDRYYnD9MS22tL3YV5Kkzm85bWWDdixect5u/LQFerGLg7l563dwfwn2XS8SMpm6H8S+TbKUQ9KYQb+uOERoCs0WQUTodRi74J9cGf7IoAOKn6ysceG23TBy9B6b8Umyx94sGko7/t2CE13FCC76VL2ONBlhP6err21Twi0KEr7hXRolVEp0sRGxDKwCeM/pVORv682wGh996Mp47NRzyfLnifCsIF4rD2ROVTeESy5UtTRxbSLvYkcS0SWbr9j4NHvF2qf3df/o1mRMsTa8ef+hZrOAKMEi44vZQbO2UQnLDv1njOQ3tdHbbY8NtS3eqpPqErl4mbYjM8Jry+UtV1JKxk7Yi00TiU803V+LLtm9+94A96tAKYMR5MfbsN8bF11Zz5Crk4zXGXF5jM5zw=
-  - secure: EoTW6GuLT/WNnEAB7KF/Eb7Ne2DbMQ6auQaPwwrhIrpsgioq7MfOzmv+OE+wtiCUExR0CruvyhRSBvnXYgBjJ+AMyPqkC73ZwFKcQGhXQkuC+LLO7U7aFyHbX2UnMSXFIwjBMrdcIzAQgthAbQk4MTO0NcAxi9Mu9DrrBR5seFrzSWVEJuhEbLMTBpMHjFJNji37XcqQXKPiqdQMAYRUb5QBJ8mV8+39dxm/5IL8Rp6UOHUhZ0bmkO2ccBnoUlAtGOgWaTLPCQgidI++4yFSA1zJYp6Z6EYQHZgIUzdBtnPNCuw8PAhwQvcu+jWFNQaS/hDWDQ1ue27u/ZKTOYmxKJAwLmkG5Ega+D+sqXuih/03PMASL3O9b1sUVc1ilukFVRB2B7EuW+ujlyYaeed3b0aUUJI6Aphtd3tJoFd79zWcQ0XJNNvMFoRqGqKcE/MwIVjNyyP97m1KZ/PQVO4UiAhFnTxhojBvmk/3XX0kLgfUH4ujfvQXyB0G4fawCZZKE3AukZkUz2yd/C7bUyEMn2nnUe0PJHPG6XL9WUZZzKPSNUHDc19TQqDROYu+iB8AvoIwy/VqzGQjw+FE+kCXvpHa/9V91cURr1mtvA5wmNIRTI/HMxBRJ2khCm2/jidRw+Z2sh1hJIHBuT1DvBrb0OqqKJh4wDhlIkT6yGx5F2A=
-  - secure: Wxp4SIJrGetnf1G1qvg5LLWPc2JDkqf2pQfXV+nZr76lyhkrerEDBcslzuAxYQMe3YCEgio5Ayk9owZjyIHjoO6Kef77cBL3QsXq51qYJT5GIhdaSGk5p7BCwy9lYaV90ljebEKSnpRO9zElh6grc3THlqUe4VScPmoMVeUP6RGRp15F+L8ecy+kEEbtMpks25htOQttqGZqvIn6uM64gdjFi/ZNZi2PN0FH0MFP2+440PvbAJpUl8Ev+tkaohiuWSv4gg1jxUO7QA0g+tNaCfstUadxxnDvAItTnFW3RzZU0Kpj3xtjf8TzaI2Q9mTiZ/GcN3RsUSF4OZefcc3M5T4C9iD5kYHP1WXvGC6Z8HOW4aHSZluD8g+l+I5kvCr1sQ/Ae/1k/dX1NlSZQr9UEaq2tsx/lNhI4y30Hp3OSC9wzeswcZSiA4P9G8LMoD2p3y18V+XCis8Nt8Eg7kjc0TqeMu2Ltx04ZtNB28faEPBNfrdSEFsPt3+H5fgRUDkfK7n7IW54i7AUnQx/UG+ewL+IoQLkDeXUxlytwvDYyZAKMf5ZSV15uiNHz/Kq6++TPcDpeO3SSoFAWlUj8xeQC2R6a9n4o03T/J0d/hTS7A0p7VRW0b/VIiZ7QPeo6JIosMUDkjwpon0otTio2MtH83tdVEKHDjMy7lkKJgSIQwU=
-  - secure: a5Rkh6GjYQFILfnhVfX0ubdngpuCD2e0rXicD1+wzOBw46PoyWqzJshAFOJHS2C8IWfxe42KWD1uckzt1mxw2eETOM7r5Pp3DAeYchTWziHL3EEL1WG62wMdvxQRGSBz20N08DDfyK65g/2a+DQv8x8ZayZivg7wZc22fPOFEp8qDBetKs+LaEnAnxLBnuwhEKbGrXJ2kFBhKBLeAq7De759SFKBca8K5SVkRfgwqjnh/3i+oPBUketwztiXee5m36vFVjWoMxEF7t2kQO8I18Eew2syD/nOm6BzH06PyStsadoYcK381h7HUVUYNqMQk6l4mDFXNbNIrap8/spuOeVDsYI+O68Zh1mfnJfJDxFuiFzXVfvp+YxeT1aY2Yk4gstCWPUBUxHdLNuZrdMUO18boHXqQDiRKXHQl26pq7WTddNC/l3MTpufBN2EOQKqrUvKSb0YaEwit9Wq1IuIZsC0+UnqyhMTIhZIuD3HY/Mdm9FmwF0v8/a40I+aRIiqc6FSG20Warn2pKFNULRTGwgTn2JXdtsqNov+jD4gHLYLu1AHssHDZD8IcFXxylXF4VvF2Y030i22rUfP10kmfBqphFyGRs+vB3E01S02mlXnRXzRf95RzqXEzK1ezyb6vfZciZ966HPhybbbtoNBamvm/rWVHg5xNod5oeu1OI4=
-  - secure: MK7zDaxpLwT+ItLDPMzc5SQOmtVrWAsc+cbCtPaYlFdXb8zKc4U3W8oIDNHajvwGPW+jB3vN0xarfiC7H9+q+I/JEViIgHGXwOt/P75tdIf7IkUHmOeEEbOHBsuV8roFOzDu4XkrYNkJG5qWxOvLtG+f4jW3bCZGL5FxdS2QIn5qBqy1v85QBrV1FKNKw+DOvHieGRul7MlGHAPCq5WWx/xyoxD1y1mDdTlFPduetcjOstsHd110Kr9SFUVu7jmvTU13S3mdkRGGN1FX3tWHiBLwhyIOOI0otuLfzq/9gsLtEoWH32/IKtMwH+Uu45gFn2ddP1cL4J42JxQcEJnE9e23E/XDuwYjV1NJBa+YgpOwUM98yBi+9AQ4+CQ+gLr+TQ6hbPyf9DqGSH0hXbY76+mnGZYSd33iVEjUdJe+82xnK/BXsqgAXXq2cIgNIjebUcgyiMHIt6s5ECzHRLcE4Hsj9lSRpEhv7fjvKq80mWsOoQa5tSoIEQx1pP/R8cyQCnX7eJBs/kbePg1Nwi3pC7WsCFxotCdxKajM7jXtdYBdHf2Fbuna3prIJEwP8lLJlBuQfwijq9DROvUovJN0wPPXuPOYX8O1LNY4wPsgX38PWzUCu2LQ6u0ztAWPio/7ZnxvbPysVMrMI2ENAadUotlDuGaSA7UhT0CAmbdexjo=
+  - secure: RSQJ+EfldTf9PA4pCfxPEf3HMCDZ1jcf+6NU3uwjOxxpDhnnmW6cUwZydheUhjZawXmk+oYzI/6aqsrGR4fq/9w7ey1gpiDeNCUKFPAcJgwb9P3R6TUgQZvin09Mgp7xK3hTXtbdXHPSbaGrXH+mh49AxGw7e9ZCtQ/f0ENUYdfAWiGqPI4W6ojJCyxiWzV+pJ0TW7JM32So98KPLQZNrBwTa0+O6I7tJcYPq62kP2jaWIwkXIb3eTKLrACYW2nKTTWVY17KfJIw/BO4ZtPwk8/EgL8E+NFEczldPbkg81QXsPRDcuQOqNnBsSD78Ej+5pjF6o715BTPYVTOcDNY5ebJ37W6SAvuOIcANwAmcrkuAtdueaHtv6lPMnfqaBp+eDIm3r1cs2tMka67r9Z9K50GxrjNMkrlNLHIXx+TZAn1CfRMslTWzb6dcEy8ncBlKmFZE0h8yRoExwOTCaPb2BH6c92e7zRJPNb3jGwabnjT0YGmswfNx/Y5C+Xv/VptU9NYYHMkbc2VgDWasuqV95wKWsgD68P7Mrqei2wEKDqCnEjSKAsTGEx3FxgvTulNUv1KRRlqrxS8u0p6V96Fg4c3IUkziEMXjtmsAysHHDjwjZ/oDE79lnjIXAvTslVv6zTMBUepMaMQrN3hW8VZ3LPWtYAxJT3MvbNZEqb8FAw=
+  - secure: ACE5vbYP0GUp6I0aUVfKk9acqTZQdcHlVS/Zw69JIzuewxjisrT1D1/tQTtvoi/PNIG+NVbFiEvyzJGILQgVEEMJ3Bnjzg3M1oD1dGSFQQZX0VuyU16B7Dcc3qvXcwVg/hbYehBNFIMi01gXZBTsAhm9M1La6omnjWPK7zVs3x+CBw5hTTplxaIxXPlANfeOBBH5ziHUL72700yXaDOWifu5gkzCwXId6abte+4Y79XozkS7DJir6B8NB5D3XkH/TFIQ1vlRrmKpSOFigKhhAUWG2X4FT5TxZes2P3lZApU5NYHvDwXISc0sivn+hXVb8JlmEgSRzp0qQWd6BEoUG2gtV2nFE6Kc8TGCkt4d2v5e0Nmel7oMjqRe2df6TYGPu3h22tYSjXdn65+fxcfWQHorW7AmIL3bMZ9hDHHi2Fp+HaaI9vvHxJPUALSlVqCn7FLwLTC1B9MgEVlPD2g7FPGMdL6n/5CT0YTJk4/4uv/aNKllp4OAx3gOuOqT4Vw4VUTXREKvIym4vK4yWBCrPCq29WEUbSaMrBh2pctEpI9dyxJmjznUsjiJ8cGYvT1zUPVcKHgybWZrERK6zHKeIL+umobi8nAMRapSZ8WCkyIlRY3ThO8qSS2jgdjg4hqD59w2QZezzSyejsGjCwNhbInJkn2ixc+pvdoxsBVM9Yw=
+  - secure: j3GX9Cnx40e61nby/5UWmrBDHVnBP0OdKnk/PG5c5b8XPl3LH68xViI8Ifn36q8bOHDTFfiMaeKvoLHzkZsXqDJbgNY6PKP1Cd/6h+FErHwDdIc8XEaczYOCawwf/esjL0f082PIsk9MUGAc5TH0DDIVgEEXL6HibxMqbEh06JZ9urIVekQCw0woHkCSh8flyWYtJf+VYiR9+llXmhZEfxEe+BIUkL+caZUSkkC54lbbW2ENvzasLHsue6+jHEyL7NobfgodM3RvB4XZ2wdxUXUqDzkOTlOLODWpXI45afdSk+h2+co436PUVOb+eg0b0RccOWb25uueamLRv2NDqbrbYBNzrRMcFtzisMORB+NDDHAcWTuJ70q89eaFBpkB03X8y6LgM37IdYITp/T9YB3TnOfgWwG2r1luJ0q8Z1vEVX7+hGBlXWi5GVk4L+q6Os+acrT8HYxZKDa/EBjS4XCiiwhzsTloxmBUJNcxDVgzzBW9NE8pQ0ZNdjPH88Ca1oy6qdMRsuMz+WSAyZ3CF0TYPxiZ5r6Pnt8aSVSneClg+8GMwFUyO5rt7ySXJNruwhtrs7r45S8v74/pSRiI1EgN0BAb2CI8AhD2wzj2vv2MNvbI/ppLeaEFz2RCEbpARJpP6ihl2GxU6WHjrqchyAgFHMTp5YrGb0/cAVLnQ0k=
+  - secure: VScdIW+AGYKJYr8Z5U2A1xoYdHxVw1eZ2DNCk+E4r8YhyTfGup9V3hbGgngT6urkOU8qQnqI7vDjI7ZyXFdzEUXKQYZDcA3s61KkiVl7c+cZZMOkD8b8fNN8uAgVgag/f04VmR5HHU2yyzaK3BkU+QEWahRkNHdjW+pJYQpYJHEoYUzCecc5335a7j1ysJ8LGXbMYiCRL29pWrTQEpC0M1mPri9kMmY7pPSr4k/iNPrAm+OCHHlrPVmHmIOH5QEduHzPkSauiExuSt3ZzU5ZqA29EwLtkm6As20ttVCz32bW1zSRlYTmkwcBjASvS4duBvSdS65AWccnRVbOqIvZJTPByYHpUi2tzuwdLVYK68m4JD51LWfFM7PCGssva6mrDSY0MvWgMF+isGugfarhLinne+hYt/r+5JxUASzYXWBKFbce1lk4bT7wp2zO0h8Q2Cna+K+D35YROV77fDiDoxarURGsqAHvU/n7PSoEnfA8WOiugVkIPuOhYhlhui+46ahMYxL69gcu88y66AMPxEHuacxW4GpYgaF/xjV8180/c3ck02csECKOjv/BQU2bbV/ngNo+bDH5g8xiHknE9oWdVEB/dxzZmmcKroXcxz6zqbMJjn03mgqBZiEkPhRStL7cny6Juq/aDTLREooHtn7OA6zsttVOkgAdCJ1VxN8=
+  - secure: lHKgxwLtpq9ydgxQcEe8legRMq5eUL+vP7pIHnauYVcQAWmfVaEwmwVeKJubPiT43m3VaXvKUvYodeNMXj4bhe+8/jG0SSVRd9UlyWlcgFXBJUBOM5FLOhPrnc2zdaCcOg8g554VqM4Xmhu1tX93E0xzBS1B7N+cDwb4xD5D5iQ5rLIbCdK8MbdJwOZLyqKN2cQ9eZRAMy5kz2WnV0LMrm3MeyxJe+bytgf8rSCE6OchNqLRyOCikkSmMiZROzvBZH2RTS1reVJHNhKfDsCkIt+QA55M9Fjnjjvs94rMNgxZwIJhj7wIgkfA2ypAi/3ESRk/yxJqsDyiutfpq/8N4l0+VCV9KIdeLn+rqEiZz8WYYp6oCVHhe/eM8HWwGmMM1JTQfUu1W6ADb8WhUY/4e+AZMb8CRjh6bJ5wf43Z5EZNOKkXZgGQyE5je3ORuPfpG/PliuJS7hUAyMzhjPnp+DMBsOPNMS/glaZWL0GB3Fr7V2IxEQZ0MUPDEebEpuQm6VddQ2Lysw+raRZuC/c3kUBC9Rt7MIHDJjTdBQmbo3GO08ErhzKVgyCLqGKUx1WpApMXtsrb6ovk7VNXrjDsWCYyVtUbIgGCYsv7OGEhQAPMyAy9YMNT0OC/Y7n+5YDjWEjCPVW38TqtK1izbJ8mdbtY9jsy5uR9ET1aCMkXiG0=
+  - secure: gDu6CUQn7QT/9wR0wrfkYGm4dHFgpDUbsQ6SfwxCarP2waxlLpuXMdPO8TZZbHVgii+Md5JqGGJGIWzSlUwygH9WpRqyJnAfb6OWheJPusYpDyFWwiKwYMyjohKRrLk44qyvdNgVN9huBVpOHwks/vmvtFtJOfqfDwSpMplHKUEhtCeGpXzVwrH7xhiZgpylBoc3/9fvstpKfTiaGPBfDaX9NUSrl2ZGDOkixRWwisuCxNvk8+xVK3sxxJwfyuBZdzQ6S9hdGgCpUcty/mWjHtaAMtaE3sfCpuZrcZiyh4wnapWQ4P0oH5pzixOesm8ul6bGXHb7f3gj/xbX8cO9FoPESSqFWGnGugTPetvE1apuwlq1lNiv8SAHA2wLTRDkGZ8Go55ZqOHgdzlTWxQRroREzo904fERXU+txsH51AX3EakQuATXBb9KHrYfsDnHmY7YPAEjzdTPpcmny18loFvpTjzcq+TFPsQXXUA2VPO1lq/ZzGTBy26X8MshdFsc3LNIkcym6smzk1/fOJ5FT1OuH0m2AoHdUJserlWtcLyU1gPujybXRmSPQwV41CG/ANVT1Yq4+4WmQ0atdBaUvL2HkrzWjpWofpK6KAdWZ60GR86f4bSsSkuE0sgNmrfHULYqJimFFur1ATxjeCCLX5rS8mUqVHNKFHohOXfbrhg=
+  - secure: a3x1V86zVwlh9Cyf7d/jR/g7RfLEZjdIcn+jcKoJlcVMbgFcEddf7Stj7xAXe2cHiuk2cieiBCmqfOB2dzm8jL/D7xL+H6n/CXSXOy1j5xljKlTviqdg2lN0Ic/k3RuM9TCylc+kuDgsy/seKyKFp+zQvIEDpmbcLUqeblJNYYkUJ6Tugo+dmjU7/gCsxACVsYRINYr2B2ZCyJjU7AwGxBssBhmCEQqoKjhhpFkDixR243Oq8gp6zKKrnePkADXAnbQc/qCA5egsH8JCP/di/I7U6UVxf38Ks5SlRkwsNNEFhaa9hEsTlWJv0MOfTdRQCEI2+4yuxc2VAKXdw8GLzPIY4U049KrP2fiGf+q/wtJgW/JE6Ux7/qeB2xE9EpyrcspLndzHNSBYUPaa92va1r3VmjGmZLs0vV1ITR7IfMJSqg2vZhXR8GJ+uu0OiLq/CS8jLpGz3tncyQQ9P5LzCLVEv5Zy187/z7WaOGpZllecgfsr772pcM08IEMvWWrj1rc8WrOF1T/81uLSGUu6/7j8Nw8PX0778Phswb48n55qptEwF+32zmJiMxVNFhIax+BT13bjwIw6MBqZhjwGgsLgORnvSc9EBxNG3g5rOvdnaaGy5xM2El2uYk9buFui6oDgQpNXpb92IJ1giAPRCaOs2QF+G3jHHYmAcaNr24A=
+  - secure: O+kTgLPklEbq65FdltBo6lMhayc+nlw+MVPOENt5oTaMgBWhr6DzmIAXJ7UGZMl1CNv5lcg7VBn/jpsH06B3WK6IOx/SR5Fg2de7T1DjYCJmjgSuwwBNf+kB1xS6nlcbh7YXaQlD3WJnb48PToigucgTHjGPFV+dL8w9mxKRHwWEE9NAXLAiDJY0+GRz4rQrM5BOAhgFijQohrYKFDfn0r4rNYT5F7WPh1KJVQhJ6kiEXYlTIk9GP7xQ1sCjNzZmo9p1WxoXlpCDsvTcn467Vt8dBhxDyqlNfqj8kpk5dWQz56xAvQ2FKP7RAGqmjgWW4S/xAFOmw1llD7xHYQqw4oDPfUtPm9jXU+4LmWffLgZ8rpcyPOMAoWB6yHdqoNxDKh9Hh/88MBkEXCbUIPX/pG4OG/aOTdTzDOM7D+3AIXXOvXHPVdYcMgrkY6RZAgCtB4q1pd7I7Afn3xyOmUbgjVJjyO8OX7Th4SgzAMh2eOd9PqzaMEwrpR2JBMx5uC/6LxM96xNMKYqDdmztdJ71/2Xzjxh9t0vcS2QiTs83p/So0QvUBQ30Ej8Al805YpzjYxJyp+hbHYhoz8J0XIr67rtV+HLB7QLC99IJGq6ZBWaJPDgxPNliiACDk7/6DHFr6SKqbBG4JJ2t8wDey/Vra9cIO/55/izi8heeqg3TDAw=
+  - secure: fRZkr+JoUz5QMmX9D4CSCjG78FrWiUdYbRKzkGpF7MXyfvNOqES2uvH67ffgubXBoeO7IS/x+hV/UcwrPpOZKDOny8dY5bxeZVjGWKkGlioqzfgPa6DDW2t+bvdtcpoB9r0N0Kp6LVoOjjn4qdjeG+4tuPIWeaEGh02mHTe+45IrPF4jhUQYEOu5kEwF/ayuH8Svvxu/zG4cWnVJ61rooW42TCXJ6Bj1Sq7lgTrTXLFYsOiuIujQiB3hhlxVi5vfD/hwx4qZkh+S0NSVIesU1uU0SFJUZ2ZTK4NWMuGDypZ2ulB/tYAAJIrfknDXJc+D8w3YWYia7q+E1tWUtoBG91rFM3hyhK7kCB2MZrUXqif20JHYpwXne66K06xpmym0/pUvKGH2Kw/qEyZTOKGSu8sl29FfsTFDRuCc4AXoP1Zyv6gHIjllmX30aFTGe0HZOftVmgnOen109Dtz2u1qSg7JrvAaQljltvRVdVlfOQ+Ub0DWFEgfUisL5WdxMDzJZalYYqR+GQy0/Wn8F2fZz4zvQ7pR4OEQoS9bWAhwcFwKSJ2IqLtAjggrIRp+h3u1OQFXeFMdhcr415QFJaw3rKsdMzubXOgOzCipfYAQbqm4KJK7boDLT2paPIKLTN6Fkf655XorMw4TuRHsOFlRqS/DOlaM2VwZP8hjc5wT4ak=

+ 56 - 16
oss/bucket.go

@@ -9,11 +9,11 @@ import (
 	"hash"
 	"hash/crc64"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"net/url"
 	"os"
 	"strconv"
+	"strings"
 	"time"
 )
 
@@ -128,7 +128,8 @@ func (bucket Bucket) GetObject(objectKey string, options ...Option) (io.ReadClos
 	if err != nil {
 		return nil, err
 	}
-	return result.Response.Body, nil
+
+	return result.Response, nil
 }
 
 // GetObjectToFile downloads the data to a local file.
@@ -147,7 +148,7 @@ func (bucket Bucket) GetObjectToFile(objectKey, filePath string, options ...Opti
 	if err != nil {
 		return err
 	}
-	defer result.Response.Body.Close()
+	defer result.Response.Close()
 
 	// If the local file does not exist, create a new one. If it exists, overwrite it.
 	fd, err := os.OpenFile(tempFilePath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, FilePermMode)
@@ -164,7 +165,12 @@ func (bucket Bucket) GetObjectToFile(objectKey, filePath string, options ...Opti
 
 	// Compares the CRC value
 	hasRange, _, _ := isOptionSet(options, HTTPHeaderRange)
-	if bucket.getConfig().IsEnableCRC && !hasRange {
+	encodeOpt, _ := findOption(options, HTTPHeaderAcceptEncoding, nil)
+	acceptEncoding := ""
+	if encodeOpt != nil {
+		acceptEncoding = encodeOpt.(string)
+	}
+	if bucket.getConfig().IsEnableCRC && !hasRange && acceptEncoding != "gzip" {
 		result.Response.ClientCRC = result.ClientCRC.Sum64()
 		err = checkCRC(result.Response, "GetObjectToFile")
 		if err != nil {
@@ -185,7 +191,7 @@ func (bucket Bucket) GetObjectToFile(objectKey, filePath string, options ...Opti
 // error    it's nil if no error, otherwise it's an error object.
 //
 func (bucket Bucket) DoGetObject(request *GetObjectRequest, options []Option) (*GetObjectResult, error) {
-	params := map[string]interface{}{}
+	params, _ := getRawParams(options)
 	resp, err := bucket.do("GET", request.ObjectKey, params, options, nil, nil)
 	if err != nil {
 		return nil, err
@@ -208,7 +214,7 @@ func (bucket Bucket) DoGetObject(request *GetObjectRequest, options []Option) (*
 	listener := getProgressListener(options)
 
 	contentLen, _ := strconv.ParseInt(resp.Headers.Get(HTTPHeaderContentLength), 10, 64)
-	resp.Body = ioutil.NopCloser(TeeReader(resp.Body, crcCalc, contentLen, listener, nil))
+	resp.Body = TeeReader(resp.Body, crcCalc, contentLen, listener, nil)
 
 	return result, nil
 }
@@ -219,7 +225,7 @@ func (bucket Bucket) DoGetObject(request *GetObjectRequest, options []Option) (*
 // destObjectKey    the target object to copy.
 // options    options for copying an object. You can specify the conditions of copy. The valid conditions are CopySourceIfMatch,
 //            CopySourceIfNoneMatch, CopySourceIfModifiedSince, CopySourceIfUnmodifiedSince, MetadataDirective.
-//            Also you can specify the target object's attributes, such as CacheControl, ContentDisposition, ContentEncoding, Expires, 
+//            Also you can specify the target object's attributes, such as CacheControl, ContentDisposition, ContentEncoding, Expires,
 //            ServerSideEncryption, ObjectACL, Meta. Refer to the link below for more details :
 //            https://help.aliyun.com/document_detail/oss/api-reference/object/CopyObject.html
 //
@@ -303,7 +309,7 @@ func (bucket Bucket) copy(srcObjectKey, destBucketName, destObjectKey string, op
 // reader    io.Reader. The read instance for reading the data to append.
 // appendPosition    the start position to append.
 // destObjectProperties    the options for the first appending, such as CacheControl, ContentDisposition, ContentEncoding,
-//                         Expires, ServerSideEncryption, ObjectACL. 
+//                         Expires, ServerSideEncryption, ObjectACL.
 //
 // int64    the next append position, it's valid when error is nil.
 // error    it's nil if no error, otherwise it's an error object.
@@ -464,7 +470,7 @@ func (bucket Bucket) IsObjectExist(objectKey string) (bool, error) {
 // options    it contains all the filters for listing objects.
 //            It could specify a prefix filter on object keys,  the max keys count to return and the object key marker and the delimiter for grouping object names.
 //            The key marker means the returned objects' key must be greater than it in lexicographic order.
-// 
+//
 //            For example, if the bucket has 8 objects, my-object-1, my-object-11, my-object-2, my-object-21,
 //            my-object-22, my-object-3, my-object-31, my-object-32. If the prefix is my-object-2 (no other filters), then it returns
 //            my-object-2, my-object-21, my-object-22 three objects. If the marker is my-object-22 (no other filters), then it returns
@@ -474,9 +480,9 @@ func (bucket Bucket) IsObjectExist(objectKey string) (bool, error) {
 //            But if the delimiter is specified with '/', then it only returns that folder's files (no subfolder's files). The direct subfolders are in the commonPrefixes properties.
 //            For example, if the bucket has three objects fun/test.jpg, fun/movie/001.avi, fun/movie/007.avi. And if the prefix is "fun/", then it returns all three objects.
 //            But if the delimiter is '/', then only "fun/test.jpg" is returned as files and fun/movie/ is returned as common prefix.
-// 
+//
 //            For common usage scenario, check out sample/list_object.go.
-// 
+//
 // ListObjectsResponse    the return value after operation succeeds (only valid when error is nil).
 //
 func (bucket Bucket) ListObjects(options ...Option) (ListObjectsResult, error) {
@@ -802,7 +808,7 @@ func (bucket Bucket) GetObjectWithURL(signedURL string, options ...Option) (io.R
 	if err != nil {
 		return nil, err
 	}
-	return result.Response.Body, nil
+	return result.Response, nil
 }
 
 // GetObjectToFileWithURL downloads the object into a local file with the signed URL.
@@ -821,7 +827,7 @@ func (bucket Bucket) GetObjectToFileWithURL(signedURL, filePath string, options
 	if err != nil {
 		return err
 	}
-	defer result.Response.Body.Close()
+	defer result.Response.Close()
 
 	// If the file does not exist, create one. If exists, then overwrite it.
 	fd, err := os.OpenFile(tempFilePath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, FilePermMode)
@@ -838,7 +844,13 @@ func (bucket Bucket) GetObjectToFileWithURL(signedURL, filePath string, options
 
 	// Compare the CRC value. If CRC values do not match, return error.
 	hasRange, _, _ := isOptionSet(options, HTTPHeaderRange)
-	if bucket.getConfig().IsEnableCRC && !hasRange {
+	encodeOpt, _ := findOption(options, HTTPHeaderAcceptEncoding, nil)
+	acceptEncoding := ""
+	if encodeOpt != nil {
+		acceptEncoding = encodeOpt.(string)
+	}
+
+	if bucket.getConfig().IsEnableCRC && !hasRange && acceptEncoding != "gzip" {
 		result.Response.ClientCRC = result.ClientCRC.Sum64()
 		err = checkCRC(result.Response, "GetObjectToFileWithURL")
 		if err != nil {
@@ -859,7 +871,7 @@ func (bucket Bucket) GetObjectToFileWithURL(signedURL, filePath string, options
 // error    it's nil if no error, otherwise it's an error object.
 //
 func (bucket Bucket) DoGetObjectWithURL(signedURL string, options []Option) (*GetObjectResult, error) {
-	params := map[string]interface{}{}
+	params, _ := getRawParams(options)
 	resp, err := bucket.doURL("GET", signedURL, params, options, nil, nil)
 	if err != nil {
 		return nil, err
@@ -882,11 +894,39 @@ func (bucket Bucket) DoGetObjectWithURL(signedURL string, options []Option) (*Ge
 	listener := getProgressListener(options)
 
 	contentLen, _ := strconv.ParseInt(resp.Headers.Get(HTTPHeaderContentLength), 10, 64)
-	resp.Body = ioutil.NopCloser(TeeReader(resp.Body, crcCalc, contentLen, listener, nil))
+	resp.Body = TeeReader(resp.Body, crcCalc, contentLen, listener, nil)
 
 	return result, nil
 }
 
+//
+// ProcessObject apply process on the specified image file.
+//
+// The supported process includes resize, rotate, crop, watermark, format,
+// udf, customized style, etc.
+//
+//
+// objectKey	object key to process.
+// process	process string, such as "image/resize,w_100|sys/saveas,o_dGVzdC5qcGc,b_dGVzdA"
+//
+// error    it's nil if no error, otherwise it's an error object.
+//
+func (bucket Bucket) ProcessObject(objectKey string, process string) (ProcessObjectResut, error) {
+	var out ProcessObjectResut
+	params := map[string]interface{}{}
+	params["x-oss-process"] = nil
+	processData := fmt.Sprintf("%v=%v", "x-oss-process", process)
+	data := strings.NewReader(processData)
+	resp, err := bucket.do("POST", objectKey, params, nil, data, nil)
+	if err != nil {
+		return out, err
+	}
+	defer resp.Body.Close()
+
+	err = jsonUnmarshal(resp.Body, &out)
+	return out, err
+}
+
 // Private
 func (bucket Bucket) do(method, objectName string, params map[string]interface{}, options []Option,
 	data io.Reader, listener ProgressListener) (*Response, error) {

+ 53 - 2
oss/bucket_test.go

@@ -4,6 +4,7 @@ package oss
 
 import (
 	"bytes"
+	"encoding/base64"
 	"errors"
 	"fmt"
 	"io"
@@ -133,7 +134,7 @@ func (s *OssBucketSuite) TestPutObject(c *C) {
 	err = s.bucket.DeleteObject(objectName)
 	c.Assert(err, IsNil)
 
-	// Put bytes 
+	// Put bytes
 	err = s.bucket.PutObject(objectName, bytes.NewReader([]byte(objectValue)))
 	c.Assert(err, IsNil)
 
@@ -352,6 +353,13 @@ func (s *OssBucketSuite) TestSignURL(c *C) {
 	c.Assert(err.(ServiceError).Code, Equals, "SignatureDoesNotMatch")
 	c.Assert(body, IsNil)
 
+	err = s.bucket.PutObjectFromFile(objectName, "../sample/The Go Programming Language.html")
+	c.Assert(err, IsNil)
+	str, err = s.bucket.SignURL(objectName, HTTPGet, 3600, AcceptEncoding("gzip"))
+	c.Assert(err, IsNil)
+	s.bucket.GetObjectToFileWithURL(str, newFile)
+	c.Assert(err, IsNil)
+
 	os.Remove(filePath)
 	os.Remove(newFile)
 
@@ -856,6 +864,12 @@ func (s *OssBucketSuite) TestGetObject(c *C) {
 	_, err = s.bucket.GetObject(objectName, IfNoneMatch(meta.Get("Etag")))
 	c.Assert(err, NotNil)
 
+	// process
+	err = s.bucket.PutObjectFromFile(objectName, "../sample/BingWallpaper-2015-11-07.jpg")
+	c.Assert(err, IsNil)
+	_, err = s.bucket.GetObject(objectName, Process("image/format,png"))
+	c.Assert(err, IsNil)
+
 	err = s.bucket.DeleteObject(objectName)
 	c.Assert(err, IsNil)
 }
@@ -962,12 +976,18 @@ func (s *OssBucketSuite) TestGetObjectToFile(c *C) {
 	eq, err = compareFileData(newFile, val)
 	c.Assert(err, IsNil)
 	c.Assert(eq, Equals, true)
-	os.Remove(newFile)
 
 	// If-None-Match
 	err = s.bucket.GetObjectToFile(objectName, newFile, IfNoneMatch(meta.Get("Etag")))
 	c.Assert(err, NotNil)
 
+	// Accept-Encoding:gzip
+	err = s.bucket.PutObjectFromFile(objectName, "../sample/The Go Programming Language.html")
+	c.Assert(err, IsNil)
+	err = s.bucket.GetObjectToFile(objectName, newFile, AcceptEncoding("gzip"))
+	c.Assert(err, IsNil)
+
+	os.Remove(newFile)
 	err = s.bucket.DeleteObject(objectName)
 	c.Assert(err, IsNil)
 }
@@ -2048,6 +2068,37 @@ func (s *OssBucketSuite) TestRestoreObject(c *C) {
 	c.Assert(meta.Get("X-Oss-Storage-Class"), Equals, "Archive")
 }
 
+// TestProcessObject
+func (s *OssBucketSuite) TestProcessObject(c *C) {
+	objectName := objectNamePrefix + "_process_src.jpg"
+	err := s.bucket.PutObjectFromFile(objectName, "../sample/BingWallpaper-2015-11-07.jpg")
+	c.Assert(err, IsNil)
+
+	// If bucket-name not specified, it is saved to the current bucket by default.
+	destObjName := objectNamePrefix + "_process_dest_1.jpg"
+	process := fmt.Sprintf("image/resize,w_100|sys/saveas,o_%v", base64.URLEncoding.EncodeToString([]byte(destObjName)))
+	result, err := s.bucket.ProcessObject(objectName, process)
+	c.Assert(err, IsNil)
+	exist, _ := s.bucket.IsObjectExist(destObjName)
+	c.Assert(exist, Equals, true)
+	c.Assert(result.Bucket, Equals, "")
+	c.Assert(result.Object, Equals, destObjName)
+
+	destObjName = objectNamePrefix + "_process_dest_1.jpg"
+	process = fmt.Sprintf("image/resize,w_100|sys/saveas,o_%v,b_%v", base64.URLEncoding.EncodeToString([]byte(destObjName)), base64.URLEncoding.EncodeToString([]byte(s.bucket.BucketName)))
+	result, err = s.bucket.ProcessObject(objectName, process)
+	c.Assert(err, IsNil)
+	exist, _ = s.bucket.IsObjectExist(destObjName)
+	c.Assert(exist, Equals, true)
+	c.Assert(result.Bucket, Equals, s.bucket.BucketName)
+	c.Assert(result.Object, Equals, destObjName)
+
+	//no support process
+	process = fmt.Sprintf("image/resize,w_100|saveas,o_%v,b_%v", base64.URLEncoding.EncodeToString([]byte(destObjName)), base64.URLEncoding.EncodeToString([]byte(s.bucket.BucketName)))
+	result, err = s.bucket.ProcessObject(objectName, process)
+	c.Assert(err, NotNil)
+}
+
 // Private
 func createFileAndWrite(fileName string, data []byte) error {
 	os.Remove(fileName)

+ 23 - 30
oss/client_test.go

@@ -42,14 +42,14 @@ var (
 )
 
 const (
-	// Prefix of bucket name for bucket ops test
-	bucketNamePrefix = "go-sdk-test-bucket-xyzv-"
-	// Bucket name for object ops test
-	bucketName        = "go-sdk-test-bucket-xyzv-for-object"
-	archiveBucketName = "go-sdk-test-bucket-xyzv-for-archive"
-	// Object name for object ops test
-	objectNamePrefix = "go-sdk-test-object-xyzv-"
-	// STS region is one and only hangzhou
+	// prefix of bucket name for bucket ops test
+	bucketNamePrefix = "go-sdk-test-bucket-abcx-"
+	// bucket name for object ops test
+	bucketName        = "go-sdk-test-bucket-abcx-for-object"
+	archiveBucketName = "go-sdk-test-bucket-abcx-for-archive"
+	// object name for object ops test
+	objectNamePrefix = "go-sdk-test-object-abcx-"
+	// sts region is one and only hangzhou
 	stsRegion = "cn-hangzhou"
 )
 
@@ -159,14 +159,13 @@ func (s *OssClientSuite) TestCreateBucket(c *C) {
 	client.DeleteBucket(bucketNameTest)
 	err = client.CreateBucket(bucketNameTest)
 	c.Assert(err, IsNil)
+	//sleep 5 seconds after create bucket
+	time.Sleep(5 * time.Second)
 
-	// Check
-	lbr, err := client.ListBuckets()
+	// verify bucket is exist
+	found, err := client.IsBucketExist(bucketNameTest)
 	c.Assert(err, IsNil)
-
-	found := s.checkBucket(lbr.Buckets, bucketNameTest)
 	c.Assert(found, Equals, true)
-	time.Sleep(5 * time.Second)
 
 	res, err := client.GetBucketACL(bucketNameTest)
 	c.Assert(err, IsNil)
@@ -174,8 +173,9 @@ func (s *OssClientSuite) TestCreateBucket(c *C) {
 
 	err = client.DeleteBucket(bucketNameTest)
 	c.Assert(err, IsNil)
+	time.Sleep(5 * time.Second)
 
-    // CreateBucket creates with ACLPublicRead
+	// CreateBucket creates with ACLPublicRead
 	err = client.CreateBucket(bucketNameTest, ACL(ACLPublicRead))
 	c.Assert(err, IsNil)
 	time.Sleep(5 * time.Second)
@@ -239,12 +239,10 @@ func (s *OssClientSuite) TestCreateBucket(c *C) {
 		err = client.CreateBucket(bucketNameTest, StorageClass(storage))
 		c.Assert(err, IsNil)
 
-		res, err := client.ListBuckets()
+		res, err := client.GetBucketInfo(bucketNameTest)
 		c.Assert(err, IsNil)
-		exist, b := s.getBucket(res.Buckets, bucketNameTest)
-		c.Assert(exist, Equals, true)
-		c.Assert(b.Name, Equals, bucketNameTest)
-		c.Assert(b.StorageClass, Equals, string(storage))
+		c.Assert(res.BucketInfo.Name, Equals, bucketNameTest)
+		c.Assert(res.BucketInfo.StorageClass, Equals, string(storage))
 
 		// Delete
 		err = client.DeleteBucket(bucketNameTest)
@@ -285,30 +283,25 @@ func (s *OssClientSuite) TestDeleteBucket(c *C) {
 	// Create
 	err = client.CreateBucket(bucketNameTest)
 	c.Assert(err, IsNil)
+	time.Sleep(5 * time.Second)
 
 	// Check
-	lbr, err := client.ListBuckets()
+	found, err := client.IsBucketExist(bucketNameTest)
 	c.Assert(err, IsNil)
-
-	found := s.checkBucket(lbr.Buckets, bucketNameTest)
 	c.Assert(found, Equals, true)
 
 	// Delete
 	err = client.DeleteBucket(bucketNameTest)
 	c.Assert(err, IsNil)
-
-	time.Sleep(time.Second * 1)
+	time.Sleep(3 * time.Second)
 
 	// Check
-	lbr, err = client.ListBuckets()
+	found, err = client.IsBucketExist(bucketNameTest)
 	c.Assert(err, IsNil)
-
-	// Sometimes failed because of cache
-	found = s.checkBucket(lbr.Buckets, bucketNameTest)
-	//    c.Assert(found, Equals, false)
+	c.Assert(found, Equals, false)
 
 	err = client.DeleteBucket(bucketNameTest)
-	//    c.Assert(err, IsNil)
+	c.Assert(err, NotNil)
 }
 
 // TestDeleteBucketNegative

+ 15 - 2
oss/conn.go

@@ -4,6 +4,7 @@ import (
 	"bytes"
 	"crypto/md5"
 	"encoding/base64"
+	"encoding/json"
 	"encoding/xml"
 	"fmt"
 	"hash"
@@ -26,7 +27,7 @@ type Conn struct {
 	client *http.Client
 }
 
-var signKeyList = []string{"acl", "uploads", "location", "cors", "logging", "website", "referer", "lifecycle", "delete", "append", "tagging", "objectMeta", "uploadId", "partNumber", "security-token", "position", "img", "style", "styleName", "replication", "replicationProgress", "replicationLocation", "cname", "bucketInfo", "comp", "qos", "live", "status", "vod", "startTime", "endTime", "symlink", "x-oss-process", "response-content-type", "response-content-language", "response-expires", "response-cache-control", "response-content-disposition", "response-content-encoding", "udf", "udfName", "udfImage", "udfId", "udfImageDesc", "udfApplication", "comp", "udfApplicationLog", "restore"}
+var signKeyList = []string{"acl", "uploads", "location", "cors", "logging", "website", "referer", "lifecycle", "delete", "append", "tagging", "objectMeta", "uploadId", "partNumber", "security-token", "position", "img", "style", "styleName", "replication", "replicationProgress", "replicationLocation", "cname", "bucketInfo", "comp", "qos", "live", "status", "vod", "startTime", "endTime", "symlink", "x-oss-process", "response-content-type", "response-content-language", "response-expires", "response-cache-control", "response-content-disposition", "response-content-encoding", "udf", "udfName", "udfImage", "udfId", "udfImageDesc", "udfApplication", "comp", "udfApplicationLog", "restore", "callback", "callback-var"}
 
 // init initializes Conn
 func (conn *Conn) init(config *Config, urlMaker *urlMaker) error {
@@ -440,6 +441,14 @@ func xmlUnmarshal(body io.Reader, v interface{}) error {
 	return xml.Unmarshal(data, v)
 }
 
+func jsonUnmarshal(body io.Reader, v interface{}) error {
+	data, err := ioutil.ReadAll(body)
+	if err != nil {
+		return err
+	}
+	return json.Unmarshal(data, v)
+}
+
 // timeoutConn handles HTTP timeout
 type timeoutConn struct {
 	conn        net.Conn
@@ -524,7 +533,11 @@ func (um *urlMaker) Init(endpoint string, isCname bool, isProxy bool) {
 	host, _, err := net.SplitHostPort(um.NetLoc)
 	if err != nil {
 		host = um.NetLoc
+		if host[0] == '[' && host[len(host)-1] == ']' {
+			host = host[1 : len(host)-1]
+		}
 	}
+
 	ip := net.ParseIP(host)
 	if ip != nil {
 		um.Type = urlTypeIP
@@ -587,7 +600,7 @@ func (um urlMaker) buildURL(bucket, object string) (string, string) {
 	return host, path
 }
 
-// getResource gets canonicalized resource 
+// getResource gets canonicalized resource
 func (um urlMaker) getResource(bucketName, objectName, subResource string) string {
 	if subResource != "" {
 		subResource = "?" + subResource

+ 18 - 0
oss/conn_test.go

@@ -2,6 +2,7 @@ package oss
 
 import (
 	"net/http"
+	"os"
 
 	. "gopkg.in/check.v1"
 )
@@ -67,6 +68,16 @@ func (s *OssConnSuite) TestURLMarker(c *C) {
 	c.Assert(um.Type, Equals, urlTypeIP)
 	c.Assert(um.Scheme, Equals, "https")
 	c.Assert(um.NetLoc, Equals, "127.0.0.1:8080")
+
+	um.Init("http://[2401:b180::dc]", false, false)
+	c.Assert(um.Type, Equals, urlTypeIP)
+	c.Assert(um.Scheme, Equals, "http")
+	c.Assert(um.NetLoc, Equals, "[2401:b180::dc]")
+
+	um.Init("https://[2401:b180::dc]:8080", false, false)
+	c.Assert(um.Type, Equals, urlTypeIP)
+	c.Assert(um.Scheme, Equals, "https")
+	c.Assert(um.NetLoc, Equals, "[2401:b180::dc]:8080")
 }
 
 func (s *OssConnSuite) TestAuth(c *C) {
@@ -123,4 +134,11 @@ func (s *OssConnSuite) TestConnToolFunc(c *C) {
 	unexpect := UnexpectedStatusCodeError{[]int{200}, 202}
 	c.Assert(len(unexpect.Error()) > 0, Equals, true)
 	c.Assert(unexpect.Got(), Equals, 202)
+
+	fd, err := os.Open("../sample/BingWallpaper-2015-11-07.jpg")
+	c.Assert(err, IsNil)
+	fd.Close()
+	var out ProcessObjectResut
+	err = jsonUnmarshal(fd, &out)
+	c.Assert(err, NotNil)
 }

+ 6 - 3
oss/const.go

@@ -106,6 +106,9 @@ const (
 	HTTPHeaderOssRequestID                   = "X-Oss-Request-Id"
 	HTTPHeaderOssCRC64                       = "X-Oss-Hash-Crc64ecma"
 	HTTPHeaderOssSymlinkTarget               = "X-Oss-Symlink-Target"
+	HTTPHeaderOssStorageClass                = "X-Oss-Storage-Class"
+	HTTPHeaderOssCallback                    = "X-Oss-Callback"
+	HTTPHeaderOssCallbackVar                 = "X-Oss-Callback-Var"
 )
 
 // HTTP Param
@@ -123,10 +126,10 @@ const (
 
 	FilePermMode = os.FileMode(0664) // Default file permission
 
-	TempFilePrefix = "oss-go-temp-"  // Temp file prefix
-	TempFileSuffix = ".temp"         // Temp file suffix
+	TempFilePrefix = "oss-go-temp-" // Temp file prefix
+	TempFileSuffix = ".temp"        // Temp file suffix
 
-	CheckpointFileSuffix = ".cp"     // Checkpoint file suffix
+	CheckpointFileSuffix = ".cp" // Checkpoint file suffix
 
 	Version = "1.9.0" // Go SDK version
 )

+ 8 - 0
oss/model.go

@@ -15,6 +15,14 @@ type Response struct {
 	ServerCRC  uint64
 }
 
+func (r *Response) Read(p []byte) (n int, err error) {
+	return r.Body.Read(p)
+}
+
+func (r *Response) Close() error {
+	return r.Body.Close()
+}
+
 // PutObjectRequest is the request of DoPutObject
 type PutObjectRequest struct {
 	ObjectKey string

+ 15 - 3
oss/multipart.go

@@ -5,6 +5,7 @@ import (
 	"encoding/xml"
 	"io"
 	"net/http"
+	"net/url"
 	"os"
 	"sort"
 	"strconv"
@@ -13,7 +14,7 @@ import (
 // InitiateMultipartUpload initializes multipart upload
 //
 // objectKey    object name
-// options    the object constricts for upload. The valid options are CacheControl, ContentDisposition, ContentEncoding, Expires, 
+// options    the object constricts for upload. The valid options are CacheControl, ContentDisposition, ContentEncoding, Expires,
 //            ServerSideEncryption, Meta, check out the following link:
 //            https://help.aliyun.com/document_detail/oss/api-reference/multipart-upload/InitiateMultipartUpload.html
 //
@@ -151,7 +152,7 @@ func (bucket Bucket) UploadPartCopy(imur InitiateMultipartUploadResult, srcBucke
 	var out UploadPartCopyResult
 	var part UploadPart
 
-	opts := []Option{CopySource(srcBucketName, srcObjectKey),
+	opts := []Option{CopySource(srcBucketName, url.QueryEscape(srcObjectKey)),
 		CopySourceRange(startPosition, partSize)}
 	opts = append(opts, options...)
 	params := map[string]interface{}{}
@@ -231,9 +232,16 @@ func (bucket Bucket) AbortMultipartUpload(imur InitiateMultipartUploadResult) er
 // ListUploadedPartsResponse    the return value if it succeeds, only valid when error is nil.
 // error    it's nil if the operation succeeds, otherwise it's an error object.
 //
-func (bucket Bucket) ListUploadedParts(imur InitiateMultipartUploadResult) (ListUploadedPartsResult, error) {
+func (bucket Bucket) ListUploadedParts(imur InitiateMultipartUploadResult, options ...Option) (ListUploadedPartsResult, error) {
 	var out ListUploadedPartsResult
+	options = append(options, EncodingType("url"))
+
 	params := map[string]interface{}{}
+	params, err := getRawParams(options)
+	if err != nil {
+		return out, err
+	}
+
 	params["uploadId"] = imur.UploadID
 	resp, err := bucket.do("GET", imur.Key, params, nil, nil, nil)
 	if err != nil {
@@ -242,6 +250,10 @@ func (bucket Bucket) ListUploadedParts(imur InitiateMultipartUploadResult) (List
 	defer resp.Body.Close()
 
 	err = xmlUnmarshal(resp.Body, &out)
+	if err != nil {
+		return out, err
+	}
+	err = decodeListUploadedPartsResult(&out)
 	return out, err
 }
 

+ 2 - 2
oss/multipart_test.go

@@ -622,7 +622,7 @@ func (s *OssBucketMultipartSuite) TestMultipartNegative(c *C) {
 	imur, err := s.bucket.InitiateMultipartUpload(string(data))
 	c.Assert(err, NotNil)
 
-	// Invalid imur 
+	// Invalid imur
 	fileName := "../sample/BingWallpaper-2015-11-07.jpg"
 	fd, err := os.Open(fileName)
 	c.Assert(err, IsNil)
@@ -668,7 +668,7 @@ func (s *OssBucketMultipartSuite) TestMultipartNegative(c *C) {
 	err = s.bucket.AbortMultipartUpload(imur)
 	c.Assert(err, IsNil)
 
-	// Invalid option 
+	// Invalid option
 	_, err = s.bucket.InitiateMultipartUpload(objectName, IfModifiedSince(futureDate))
 	c.Assert(err, IsNil)
 }

+ 28 - 2
oss/option.go

@@ -172,6 +172,21 @@ func Origin(value string) Option {
 	return setHeader(HTTPHeaderOrigin, value)
 }
 
+// ObjectStorageClass is an option to set the storage class of object
+func ObjectStorageClass(storageClass StorageClassType) Option {
+	return setHeader(HTTPHeaderOssStorageClass, string(storageClass))
+}
+
+// Callback is an option to set callback values
+func Callback(callback string) Option {
+	return setHeader(HTTPHeaderOssCallback, callback)
+}
+
+// CallbackVar is an option to set callback user defined values
+func CallbackVar(callbackVar string) Option {
+	return setHeader(HTTPHeaderOssCallbackVar, callbackVar)
+}
+
 // Delimiter is an option to set delimiler parameter
 func Delimiter(value string) Option {
 	return addParam("delimiter", value)
@@ -212,6 +227,16 @@ func UploadIDMarker(value string) Option {
 	return addParam("upload-id-marker", value)
 }
 
+// MaxParts is an option to set max-parts parameter
+func MaxParts(value int) Option {
+	return addParam("max-parts", strconv.Itoa(value))
+}
+
+// PartNumberMarker is an option to set part-number-marker parameter
+func PartNumberMarker(value int) Option {
+	return addParam("part-number-marker", strconv.Itoa(value))
+}
+
 // DeleteObjectsQuiet false:DeleteObjects in verbose mode; true:DeleteObjects in quite mode. Default is false.
 func DeleteObjectsQuiet(isQuiet bool) Option {
 	return addArg(deleteObjectsQuiet, isQuiet)
@@ -278,10 +303,11 @@ func ResponseContentEncoding(value string) Option {
 	return addParam("response-content-encoding", value)
 }
 
-// Process is an option to set X-Oss-Process param
+// Process is an option to set x-oss-process param
 func Process(value string) Option {
-	return addParam("X-Oss-Process", value)
+	return addParam("x-oss-process", value)
 }
+
 func setHeader(key string, value interface{}) Option {
 	return func(params map[string]optionValue) error {
 		if value == nil {

+ 31 - 1
oss/option_test.go

@@ -127,6 +127,21 @@ var headerTestcases = []optionTestCase{
 		key:    "X-Oss-Object-Acl",
 		value:  "private",
 	},
+	{
+		option: ObjectStorageClass(StorageStandard),
+		key:    "X-Oss-Storage-Class",
+		value:  "Standard",
+	},
+	{
+		option: Callback("JTdCJTIyY2FsbGJhY2tVcmwlMjIlM0ElMjJleGFtcGxlLmNvbS9pbmRleC5odG1sJTIyJTdE"),
+		key:    "X-Oss-Callback",
+		value:  "JTdCJTIyY2FsbGJhY2tVcmwlMjIlM0ElMjJleGFtcGxlLmNvbS9pbmRleC5odG1sJTIyJTdE",
+	},
+	{
+		option: CallbackVar("JTdCJTIyeCUzQXZhcjElMjIlM0ElMjJ2YWx1ZTElMjIlMkMlMjJ4JTNBdmFyMiUyMiUzQSUyMnZhbHVlMiUyMiU3RA=="),
+		key:    "X-Oss-Callback-Var",
+		value:  "JTdCJTIyeCUzQXZhcjElMjIlM0ElMjJ2YWx1ZTElMjIlMkMlMjJ4JTNBdmFyMiUyMiUzQSUyMnZhbHVlMiUyMiU3RA==",
+	},
 }
 
 func (s *OssOptionSuite) TestHeaderOptions(c *C) {
@@ -181,6 +196,21 @@ var paramTestCases = []optionTestCase{
 		key:    "upload-id-marker",
 		value:  "xyz",
 	},
+	{
+		option: MaxParts(1000),
+		key:    "max-parts",
+		value:  "1000",
+	},
+	{
+		option: PartNumberMarker(1),
+		key:    "part-number-marker",
+		value:  "1",
+	},
+	{
+		option: Process("image/format,png"),
+		key:    "x-oss-process",
+		value:  "image/format,png",
+	},
 }
 
 func (s *OssOptionSuite) TestParamOptions(c *C) {
@@ -231,7 +261,7 @@ func (s *OssOptionSuite) TestHandleParams(c *C) {
 	c.Assert(err, IsNil)
 
 	out := client.Conn.getURLParams(params)
-	c.Assert(len(out), Equals, 120)
+	c.Assert(len(out), Equals, 191)
 
 	options = []Option{KeyMarker(""), nil}
 

+ 8 - 1
oss/progress.go

@@ -62,7 +62,7 @@ type teeReader struct {
 // corresponding writes to w.  There is no internal buffering -
 // the write must complete before the read completes.
 // Any error encountered while writing is reported as a read error.
-func TeeReader(reader io.Reader, writer io.Writer, totalBytes int64, listener ProgressListener, tracker *readerTracker) io.Reader {
+func TeeReader(reader io.Reader, writer io.Writer, totalBytes int64, listener ProgressListener, tracker *readerTracker) io.ReadCloser {
 	return &teeReader{
 		reader:        reader,
 		writer:        writer,
@@ -103,3 +103,10 @@ func (t *teeReader) Read(p []byte) (n int, err error) {
 
 	return
 }
+
+func (t *teeReader) Close() error {
+	if rc, ok := t.reader.(io.ReadCloser); ok {
+		return rc.Close()
+	}
+	return nil
+}

+ 18 - 0
oss/type.go

@@ -363,6 +363,14 @@ type UncompletedUpload struct {
 	Initiated time.Time `xml:"Initiated"` // Initialization time in the format such as 2012-02-23T04:18:23.000Z
 }
 
+// ProcessObjectResut defines result object of ProcessObject
+type ProcessObjectResut struct {
+	Bucket   string `json:"bucket"`
+	FileSize int    `json:"fileSize"`
+	Object   string `json:"object"`
+	Status   string `json:"status"`
+}
+
 // decodeDeleteObjectsResult decodes deleting objects result in URL encoding
 func decodeDeleteObjectsResult(result *DeleteObjectsResult) error {
 	var err error
@@ -409,6 +417,16 @@ func decodeListObjectsResult(result *ListObjectsResult) error {
 	return nil
 }
 
+// decodeListUploadedPartsResult decodes
+func decodeListUploadedPartsResult(result *ListUploadedPartsResult) error {
+	var err error
+	result.Key, err = url.QueryUnescape(result.Key)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
 // decodeListMultipartUploadResult decodes list multipart upload result in URL encoding
 func decodeListMultipartUploadResult(result *ListMultipartUploadResult) error {
 	var err error

+ 1 - 1
sample/bucket_referer.go

@@ -40,7 +40,7 @@ func BucketRefererSample() {
 	}
 
 	// Get bucket referer configuration
-	gbr, err := client.GetBucketReferqer(bucketName)
+	gbr, err := client.GetBucketReferer(bucketName)
 	if err != nil {
 		HandleError(err)
 	}