From f8625fe4470516be5e2b58f22fcdc339f897cfe7 Mon Sep 17 00:00:00 2001 From: Bachue Zhou Date: Tue, 5 Sep 2023 16:09:05 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=20proxy=20(#419)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test-ci.yml | 15 ++++ src/Qiniu/Cdn/CdnManager.php | 7 +- src/Qiniu/Config.php | 66 ++++++++-------- src/Qiniu/Http/Client.php | 3 +- src/Qiniu/Http/Proxy.php | 34 ++++++++ src/Qiniu/Http/RequestOptions.php | 35 ++++++++- src/Qiniu/Processing/Operation.php | 15 +++- src/Qiniu/Processing/PersistentFop.php | 13 +++- src/Qiniu/Region.php | 24 +++++- src/Qiniu/Rtc/AppClient.php | 12 +-- src/Qiniu/Sms/Sms.php | 14 ++-- src/Qiniu/Storage/ArgusManager.php | 18 +++-- src/Qiniu/Storage/BucketManager.php | 62 +++++++++++---- src/Qiniu/Storage/FormUploader.php | 4 +- src/Qiniu/Storage/ResumeUploader.php | 6 +- src/Qiniu/Zone.php | 12 ++- tests/Qiniu/Tests/FormUpTest.php | 103 ++++++++++++++++++++++++- tests/Qiniu/Tests/HttpTest.php | 12 +++ tests/Qiniu/Tests/ResumeUpTest.php | 44 ++++++++++- tests/socks5-server/go.mod | 7 ++ tests/socks5-server/go.sum | 4 + tests/socks5-server/main.go | 24 ++++++ 22 files changed, 442 insertions(+), 92 deletions(-) create mode 100644 src/Qiniu/Http/Proxy.php create mode 100644 tests/socks5-server/go.mod create mode 100644 tests/socks5-server/go.sum create mode 100644 tests/socks5-server/main.go diff --git a/.github/workflows/test-ci.yml b/.github/workflows/test-ci.yml index 780117e4..c76b39e5 100644 --- a/.github/workflows/test-ci.yml +++ b/.github/workflows/test-ci.yml @@ -18,11 +18,20 @@ jobs: with: php-version: '8.2' + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: '1.21.x' + - name: Setup build-in server run: | nohup php -S localhost:9000 -t ./tests/mock-server/ > phpd.log 2>&1 & echo $! > mock-server.pid + cd tests/socks5-server/ + nohup go run main.go > ../../socks5.log 2>&1 & + echo $! > ../../socks-server.pid + - name: Setup php uses: shivammathur/setup-php@v2 with: @@ -40,6 +49,7 @@ jobs: ./vendor/bin/phpcs --standard=PSR2 tests ./vendor/bin/phpunit --coverage-clover=coverage.xml cat mock-server.pid | xargs kill + cat socks-server.pid | xargs kill env: QINIU_ACCESS_KEY: ${{ secrets.QINIU_ACCESS_KEY }} @@ -52,5 +62,10 @@ jobs: run: | cat phpd.log + - name: Print socks5 server log + if: ${{ failure() }} + run: | + cat socks5.log + - name: After_success run: bash <(curl -s https://codecov.io/bash) diff --git a/src/Qiniu/Cdn/CdnManager.php b/src/Qiniu/Cdn/CdnManager.php index a6efcedb..60052d3e 100644 --- a/src/Qiniu/Cdn/CdnManager.php +++ b/src/Qiniu/Cdn/CdnManager.php @@ -5,17 +5,20 @@ use Qiniu\Auth; use Qiniu\Http\Error; use Qiniu\Http\Client; +use Qiniu\Http\Proxy; final class CdnManager { private $auth; private $server; + private $proxy; - public function __construct(Auth $auth) + public function __construct(Auth $auth, $proxy = null, $proxy_auth = null, $proxy_user_password = null) { $this->auth = $auth; $this->server = 'http://fusion.qiniuapi.com'; + $this->proxy = new Proxy($proxy, $proxy_auth, $proxy_user_password); } /** @@ -225,7 +228,7 @@ private function post($url, $body) { $headers = $this->auth->authorization($url, $body, 'application/json'); $headers['Content-Type'] = 'application/json'; - $ret = Client::post($url, $body, $headers); + $ret = Client::post($url, $body, $headers, $this->proxy->makeReqOpt()); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } diff --git a/src/Qiniu/Config.php b/src/Qiniu/Config.php index d274b2bc..b47dfbb8 100644 --- a/src/Qiniu/Config.php +++ b/src/Qiniu/Config.php @@ -1,4 +1,5 @@ backupQueryRegionHosts; } - public function getUpHost($accessKey, $bucket) + public function getUpHost($accessKey, $bucket, $reqOpt = null) { - $region = $this->getRegion($accessKey, $bucket); + $region = $this->getRegion($accessKey, $bucket, $reqOpt); if ($this->useHTTPS === true) { $scheme = "https://"; } else { @@ -116,9 +117,9 @@ public function getUpHost($accessKey, $bucket) return $scheme . $host; } - public function getUpHostV2($accessKey, $bucket) + public function getUpHostV2($accessKey, $bucket, $reqOpt = null) { - list($region, $err) = $this->getRegionV2($accessKey, $bucket); + list($region, $err) = $this->getRegionV2($accessKey, $bucket, $reqOpt); if ($err != null) { return array(null, $err); } @@ -137,9 +138,9 @@ public function getUpHostV2($accessKey, $bucket) return array($scheme . $host, null); } - public function getUpBackupHost($accessKey, $bucket) + public function getUpBackupHost($accessKey, $bucket, $reqOpt = null) { - $region = $this->getRegion($accessKey, $bucket); + $region = $this->getRegion($accessKey, $bucket, $reqOpt); if ($this->useHTTPS === true) { $scheme = "https://"; } else { @@ -154,9 +155,9 @@ public function getUpBackupHost($accessKey, $bucket) return $scheme . $host; } - public function getUpBackupHostV2($accessKey, $bucket) + public function getUpBackupHostV2($accessKey, $bucket, $reqOpt = null) { - list($region, $err) = $this->getRegionV2($accessKey, $bucket); + list($region, $err) = $this->getRegionV2($accessKey, $bucket, $reqOpt); if ($err != null) { return array(null, $err); } @@ -175,9 +176,9 @@ public function getUpBackupHostV2($accessKey, $bucket) return array($scheme . $host, null); } - public function getRsHost($accessKey, $bucket) + public function getRsHost($accessKey, $bucket, $reqOpt = null) { - $region = $this->getRegion($accessKey, $bucket); + $region = $this->getRegion($accessKey, $bucket, $reqOpt); if ($this->useHTTPS === true) { $scheme = "https://"; @@ -188,9 +189,9 @@ public function getRsHost($accessKey, $bucket) return $scheme . $region->rsHost; } - public function getRsHostV2($accessKey, $bucket) + public function getRsHostV2($accessKey, $bucket, $reqOpt = null) { - list($region, $err) = $this->getRegionV2($accessKey, $bucket); + list($region, $err) = $this->getRegionV2($accessKey, $bucket, $reqOpt); if ($err != null) { return array(null, $err); } @@ -204,9 +205,9 @@ public function getRsHostV2($accessKey, $bucket) return array($scheme . $region->rsHost, null); } - public function getRsfHost($accessKey, $bucket) + public function getRsfHost($accessKey, $bucket, $reqOpt = null) { - $region = $this->getRegion($accessKey, $bucket); + $region = $this->getRegion($accessKey, $bucket, $reqOpt); if ($this->useHTTPS === true) { $scheme = "https://"; @@ -217,9 +218,9 @@ public function getRsfHost($accessKey, $bucket) return $scheme . $region->rsfHost; } - public function getRsfHostV2($accessKey, $bucket) + public function getRsfHostV2($accessKey, $bucket, $reqOpt = null) { - list($region, $err) = $this->getRegionV2($accessKey, $bucket); + list($region, $err) = $this->getRegionV2($accessKey, $bucket, $reqOpt); if ($err != null) { return array(null, $err); } @@ -233,9 +234,9 @@ public function getRsfHostV2($accessKey, $bucket) return array($scheme . $region->rsfHost, null); } - public function getIovipHost($accessKey, $bucket) + public function getIovipHost($accessKey, $bucket, $reqOpt = null) { - $region = $this->getRegion($accessKey, $bucket); + $region = $this->getRegion($accessKey, $bucket, $reqOpt); if ($this->useHTTPS === true) { $scheme = "https://"; @@ -246,9 +247,9 @@ public function getIovipHost($accessKey, $bucket) return $scheme . $region->iovipHost; } - public function getIovipHostV2($accessKey, $bucket) + public function getIovipHostV2($accessKey, $bucket, $reqOpt = null) { - list($region, $err) = $this->getRegionV2($accessKey, $bucket); + list($region, $err) = $this->getRegionV2($accessKey, $bucket, $reqOpt); if ($err != null) { return array(null, $err); } @@ -262,9 +263,9 @@ public function getIovipHostV2($accessKey, $bucket) return array($scheme . $region->iovipHost, null); } - public function getApiHost($accessKey, $bucket) + public function getApiHost($accessKey, $bucket, $reqOpt = null) { - $region = $this->getRegion($accessKey, $bucket); + $region = $this->getRegion($accessKey, $bucket, $reqOpt); if ($this->useHTTPS === true) { $scheme = "https://"; @@ -275,9 +276,9 @@ public function getApiHost($accessKey, $bucket) return $scheme . $region->apiHost; } - public function getApiHostV2($accessKey, $bucket) + public function getApiHostV2($accessKey, $bucket, $reqOpt = null) { - list($region, $err) = $this->getRegionV2($accessKey, $bucket); + list($region, $err) = $this->getRegionV2($accessKey, $bucket, $reqOpt); if ($err != null) { return array(null, $err); } @@ -302,8 +303,7 @@ private function getRegionCache($cacheId) { if (isset($this->regionCache[$cacheId]) && isset($this->regionCache[$cacheId]["deadline"]) && - time() < $this->regionCache[$cacheId]["deadline"] - ) { + time() < $this->regionCache[$cacheId]["deadline"]) { return $this->regionCache[$cacheId]["region"]; } @@ -336,7 +336,7 @@ private function setRegionCache($cacheId, $region) * * @throws \Exception */ - private function getRegion($accessKey, $bucket) + private function getRegion($accessKey, $bucket, $reqOpt = null) { if (isset($this->zone)) { return $this->zone; @@ -353,7 +353,8 @@ private function getRegion($accessKey, $bucket) $bucket, $this->getQueryRegionHost(), $this->getBackupQueryRegionHosts(), - $this->backupUcHostsRetryTimes + $this->backupUcHostsRetryTimes, + $reqOpt ); if (is_array($region)) { list($region, $err) = $region; @@ -366,7 +367,7 @@ private function getRegion($accessKey, $bucket) return $region; } - private function getRegionV2($accessKey, $bucket) + private function getRegionV2($accessKey, $bucket, $reqOpt = null) { if (isset($this->zone)) { return array($this->zone, null); @@ -383,7 +384,8 @@ private function getRegionV2($accessKey, $bucket) $bucket, $this->getQueryRegionHost(), $this->getBackupQueryRegionHosts(), - $this->backupUcHostsRetryTimes + $this->backupUcHostsRetryTimes, + $reqOpt ); if (is_array($region)) { list($region, $err) = $region; diff --git a/src/Qiniu/Http/Client.php b/src/Qiniu/Http/Client.php index b5b3321e..8ea8475e 100644 --- a/src/Qiniu/Http/Client.php +++ b/src/Qiniu/Http/Client.php @@ -1,4 +1,5 @@ self::userAgent(), CURLOPT_RETURNTRANSFER => true, - CURLOPT_SSL_VERIFYPEER => false, - CURLOPT_SSL_VERIFYHOST => false, CURLOPT_HEADER => true, CURLOPT_NOBODY => false, CURLOPT_CUSTOMREQUEST => $request->method, diff --git a/src/Qiniu/Http/Proxy.php b/src/Qiniu/Http/Proxy.php new file mode 100644 index 00000000..fac6ba15 --- /dev/null +++ b/src/Qiniu/Http/Proxy.php @@ -0,0 +1,34 @@ +proxy = $proxy; + $this->proxy_auth = $proxy_auth; + $this->proxy_user_password = $proxy_user_password; + } + + public function makeReqOpt() + { + $reqOpt = new RequestOptions(); + if ($this->proxy !== null) { + $reqOpt->proxy = $this->proxy; + } + if ($this->proxy_auth !== null) { + $reqOpt->proxy_auth = $this->proxy_auth; + } + if ($this->proxy_user_password !== null) { + $reqOpt->proxy_user_password = $this->proxy_user_password; + } + return $reqOpt; + } +} diff --git a/src/Qiniu/Http/RequestOptions.php b/src/Qiniu/Http/RequestOptions.php index 9babda44..be0c6d5e 100644 --- a/src/Qiniu/Http/RequestOptions.php +++ b/src/Qiniu/Http/RequestOptions.php @@ -32,6 +32,24 @@ final class RequestOptions */ public $timeout_ms; + /** + * @var string|null + * 代理URL,默认:空 + */ + public $proxy; + + /** + * @var int|null + * 代理鉴权方式,默认:空 + */ + public $proxy_auth; + + /** + * @var string|null + * 代理鉴权参数,默认:空 + */ + public $proxy_user_password; + /** * @var array */ @@ -42,12 +60,18 @@ public function __construct( $connection_timeout_ms = null, $timeout = null, $timeout_ms = null, - $middlewares = array() + $middlewares = array(), + $proxy = null, + $proxy_auth = null, + $proxy_user_password = null ) { $this->connection_timeout = $connection_timeout; $this->connection_timeout_ms = $connection_timeout_ms; $this->timeout = $timeout; $this->timeout_ms = $timeout_ms; + $this->proxy = $proxy; + $this->proxy_auth = $proxy_auth; + $this->proxy_user_password = $proxy_user_password; $this->middlewares = $middlewares; } @@ -66,6 +90,15 @@ public function getCurlOpt() if ($this->timeout_ms != null) { $result[CURLOPT_TIMEOUT_MS] = $this->timeout_ms; } + if ($this->proxy != null) { + $result[CURLOPT_PROXY] = $this->proxy; + } + if ($this->proxy_auth != null) { + $result[CURLOPT_PROXYAUTH] = $this->proxy_auth; + } + if ($this->proxy_user_password != null) { + $result[CURLOPT_PROXYUSERPWD] = $this->proxy_user_password; + } return $result; } } diff --git a/src/Qiniu/Processing/Operation.php b/src/Qiniu/Processing/Operation.php index 7cdd352b..839703c0 100644 --- a/src/Qiniu/Processing/Operation.php +++ b/src/Qiniu/Processing/Operation.php @@ -4,6 +4,7 @@ use Qiniu\Http\Client; use Qiniu\Http\Error; +use Qiniu\Http\Proxy; final class Operation { @@ -11,12 +12,20 @@ final class Operation private $auth; private $token_expire; private $domain; + private $proxy; - public function __construct($domain, $auth = null, $token_expire = 3600) - { + public function __construct( + $domain, + $auth = null, + $token_expire = 3600, + $proxy = null, + $proxy_auth = null, + $proxy_user_password = null + ) { $this->auth = $auth; $this->domain = $domain; $this->token_expire = $token_expire; + $this->proxy = new Proxy($proxy, $proxy_auth, $proxy_user_password); } @@ -34,7 +43,7 @@ public function __construct($domain, $auth = null, $token_expire = 3600) public function execute($key, $fops) { $url = $this->buildUrl($key, $fops); - $resp = Client::get($url); + $resp = Client::get($url, array(), $this->proxy->makeReqOpt()); if (!$resp->ok()) { return array(null, new Error($url, $resp)); } diff --git a/src/Qiniu/Processing/PersistentFop.php b/src/Qiniu/Processing/PersistentFop.php index ac95d251..97a4ff49 100644 --- a/src/Qiniu/Processing/PersistentFop.php +++ b/src/Qiniu/Processing/PersistentFop.php @@ -5,6 +5,7 @@ use Qiniu\Config; use Qiniu\Http\Error; use Qiniu\Http\Client; +use Qiniu\Http\Proxy; /** * 持久化处理类,该类用于主动触发异步持久化操作. @@ -23,8 +24,13 @@ final class PersistentFop * */ private $config; + /** + * @var 代理信息 + */ + private $proxy; + - public function __construct($auth, $config = null) + public function __construct($auth, $config = null, $proxy = null, $proxy_auth = null, $proxy_user_password = null) { $this->auth = $auth; if ($config == null) { @@ -32,6 +38,7 @@ public function __construct($auth, $config = null) } else { $this->config = $config; } + $this->proxy = new Proxy($proxy, $proxy_auth, $proxy_user_password); } /** @@ -68,7 +75,7 @@ public function execute($bucket, $key, $fops, $pipeline = null, $notify_url = nu $url = $scheme . Config::API_HOST . '/pfop/'; $headers = $this->auth->authorization($url, $data, 'application/x-www-form-urlencoded'); $headers['Content-Type'] = 'application/x-www-form-urlencoded'; - $response = Client::post($url, $data, $headers); + $response = Client::post($url, $data, $headers, $this->proxy->makeReqOpt()); if (!$response->ok()) { return array(null, new Error($url, $response)); } @@ -85,7 +92,7 @@ public function status($id) $scheme = "https://"; } $url = $scheme . Config::API_HOST . "/status/get/prefop?id=$id"; - $response = Client::get($url); + $response = Client::get($url, array(), $this->proxy->makeReqOpt()); if (!$response->ok()) { return array(null, new Error($url, $response)); } diff --git a/src/Qiniu/Region.php b/src/Qiniu/Region.php index d5f9620a..220a5a3c 100644 --- a/src/Qiniu/Region.php +++ b/src/Qiniu/Region.php @@ -1,4 +1,5 @@ &bucket= + * @param string $ak + * @param string $bucket + * @param string $ucHost|null + * @param array $backupUcHosts + * @param int $retryTimes + * @param RequestOptions|null $reqOpt + * @return Response **/ - public static function queryRegion($ak, $bucket, $ucHost = null, $backupUcHosts = array(), $retryTimes = 2) - { + public static function queryRegion( + $ak, + $bucket, + $ucHost = null, + $backupUcHosts = array(), + $retryTimes = 2, + $reqOpt = null + ) { $region = new Region(); if (!$ucHost) { $ucHost = "https://" . Config::QUERY_REGION_HOST; } $url = $ucHost . '/v4/query' . "?ak=$ak&bucket=$bucket"; - $reqOpt = new RequestOptions(); + if ($reqOpt == null) { + $reqOpt = new RequestOptions(); + } $reqOpt->middlewares = array( new RetryDomainsMiddleware( $backupUcHosts, $retryTimes ) ); - $ret = Client::Get($url, array(), $reqOpt); + $ret = Client::get($url, array(), $reqOpt); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } diff --git a/src/Qiniu/Rtc/AppClient.php b/src/Qiniu/Rtc/AppClient.php index 4f45aaeb..3f245db2 100755 --- a/src/Qiniu/Rtc/AppClient.php +++ b/src/Qiniu/Rtc/AppClient.php @@ -6,17 +6,19 @@ use Qiniu\Config; use Qiniu\Http\Error; use Qiniu\Http\Client; +use Qiniu\Http\Proxy; class AppClient { private $auth; private $baseURL; + private $proxy; - public function __construct(Auth $auth) + public function __construct(Auth $auth, $proxy = null, $proxy_auth = null, $proxy_user_password = null) { $this->auth = $auth; - $this->baseURL = sprintf("%s/%s/apps", Config::RTCAPI_HOST, Config::RTCAPI_VERSION); + $this->proxy = new Proxy($proxy, $proxy_auth, $proxy_user_password); } /** @@ -202,7 +204,7 @@ private function get($url, $cType = null) { $rtcToken = $this->auth->authorizationV2($url, "GET", null, $cType); $rtcToken['Content-Type'] = $cType; - $ret = Client::get($url, $rtcToken); + $ret = Client::get($url, $rtcToken, $this->proxy->makeReqOpt()); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } @@ -213,7 +215,7 @@ private function delete($url, $contentType = 'application/json') { $rtcToken = $this->auth->authorizationV2($url, "DELETE", null, $contentType); $rtcToken['Content-Type'] = $contentType; - $ret = Client::delete($url, $rtcToken); + $ret = Client::delete($url, $rtcToken, $this->proxy->makeReqOpt()); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } @@ -224,7 +226,7 @@ private function post($url, $body, $contentType = 'application/json') { $rtcToken = $this->auth->authorizationV2($url, "POST", $body, $contentType); $rtcToken['Content-Type'] = $contentType; - $ret = Client::post($url, $body, $rtcToken); + $ret = Client::post($url, $body, $rtcToken, $this->proxy->makeReqOpt()); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } diff --git a/src/Qiniu/Sms/Sms.php b/src/Qiniu/Sms/Sms.php index 625ec304..c96409b6 100644 --- a/src/Qiniu/Sms/Sms.php +++ b/src/Qiniu/Sms/Sms.php @@ -6,17 +6,19 @@ use Qiniu\Config; use Qiniu\Http\Error; use Qiniu\Http\Client; +use Qiniu\Http\Proxy; class Sms { private $auth; private $baseURL; + private $proxy; - public function __construct(Auth $auth) + public function __construct(Auth $auth, $proxy = null, $proxy_auth = null, $proxy_user_password = null) { $this->auth = $auth; - $this->baseURL = sprintf("%s/%s/", Config::SMS_HOST, Config::SMS_VERSION); + $this->proxy = new Proxy($proxy, $proxy_auth, $proxy_user_password); } /** @@ -335,7 +337,7 @@ private function get($url, $contentType = 'application/x-www-form-urlencoded') { $headers = $this->auth->authorizationV2($url, "GET", null, $contentType); $headers['Content-Type'] = $contentType; - $ret = Client::get($url, $headers); + $ret = Client::get($url, $headers, $this->proxy->makeReqOpt()); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } @@ -346,7 +348,7 @@ private function delete($url, $contentType = 'application/json') { $headers = $this->auth->authorizationV2($url, "DELETE", null, $contentType); $headers['Content-Type'] = $contentType; - $ret = Client::delete($url, $headers); + $ret = Client::delete($url, $headers, $this->proxy->makeReqOpt()); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } @@ -358,7 +360,7 @@ private function post($url, $body, $contentType = 'application/json') $headers = $this->auth->authorizationV2($url, "POST", $body, $contentType); $headers['Content-Type'] = $contentType; - $ret = Client::post($url, $body, $headers); + $ret = Client::post($url, $body, $headers, $this->proxy->makeReqOpt()); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } @@ -370,7 +372,7 @@ private function PUT($url, $body, $contentType = 'application/json') { $headers = $this->auth->authorizationV2($url, "PUT", $body, $contentType); $headers['Content-Type'] = $contentType; - $ret = Client::put($url, $body, $headers); + $ret = Client::put($url, $body, $headers, $this->proxy->makeReqOpt()); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } diff --git a/src/Qiniu/Storage/ArgusManager.php b/src/Qiniu/Storage/ArgusManager.php index 0f2baee2..5f5e5544 100644 --- a/src/Qiniu/Storage/ArgusManager.php +++ b/src/Qiniu/Storage/ArgusManager.php @@ -7,6 +7,7 @@ use Qiniu\Zone; use Qiniu\Http\Client; use Qiniu\Http\Error; +use Qiniu\Http\Proxy; /** * 主要涉及了内容审核接口的实现,具体的接口规格可以参考 @@ -17,15 +18,22 @@ final class ArgusManager { private $auth; private $config; - - public function __construct(Auth $auth, Config $config = null) - { + private $proxy; + + public function __construct( + Auth $auth, + Config $config = null, + $proxy = null, + $proxy_auth = null, + $proxy_user_password = null + ) { $this->auth = $auth; if ($config == null) { $this->config = new Config(); } else { $this->config = $config; } + $this->proxy = new Proxy($proxy, $proxy_auth, $proxy_user_password); } /** @@ -101,14 +109,14 @@ private function get($url) { $headers = $this->auth->authorizationV2($url, 'GET'); - return Client::get($url, $headers); + return Client::get($url, $headers, $this->proxy->makeReqOpt()); } private function post($url, $body) { $headers = $this->auth->authorizationV2($url, 'POST', $body, 'application/json'); $headers['Content-Type'] = 'application/json'; - $ret = Client::post($url, $body, $headers); + $ret = Client::post($url, $body, $headers, $this->proxy->makeReqOpt()); if (!$ret->ok()) { print("statusCode: " . $ret->statusCode); return array(null, new Error($url, $ret)); diff --git a/src/Qiniu/Storage/BucketManager.php b/src/Qiniu/Storage/BucketManager.php index 89b13e1e..dc66eb2a 100644 --- a/src/Qiniu/Storage/BucketManager.php +++ b/src/Qiniu/Storage/BucketManager.php @@ -6,6 +6,7 @@ use Qiniu\Config; use Qiniu\Http\Error; use Qiniu\Http\Client; +use Qiniu\Http\Proxy; /** * 主要涉及了空间资源管理及批量操作接口的实现,具体的接口规格可以参考 @@ -16,15 +17,22 @@ final class BucketManager { private $auth; private $config; - - public function __construct(Auth $auth, Config $config = null) - { + private $proxy; + + public function __construct( + Auth $auth, + Config $config = null, + $proxy = null, + $proxy_auth = null, + $proxy_user_password = null + ) { $this->auth = $auth; if ($config == null) { $this->config = new Config(); } else { $this->config = $config; } + $this->proxy = new Proxy($proxy, $proxy_auth, $proxy_user_password); } /** @@ -39,7 +47,7 @@ public function buckets($shared = true) if ($shared === true) { $includeShared = "true"; } - return $this->getV2($this->config->getUcHost(). '/buckets?shared=' . $includeShared); + return $this->getV2($this->config->getUcHost() . '/buckets?shared=' . $includeShared); } /** @@ -183,7 +191,11 @@ public function listFilesv2( \Qiniu\setWithoutEmpty($query, 'skipconfirm', $skipconfirm); $path = '/v2/list?' . http_build_query($query); - list($host, $err) = $this->config->getRsfHostV2($this->auth->getAccessKey(), $bucket); + list($host, $err) = $this->config->getRsfHostV2( + $this->auth->getAccessKey(), + $bucket, + $this->proxy->makeReqOpt() + ); if ($err != null) { return array(null, $err); @@ -191,7 +203,7 @@ public function listFilesv2( $url = $host . $path; $headers = $this->auth->authorizationV2($url, 'POST', null, 'application/x-www-form-urlencoded'); - $ret = Client::post($url, null, $headers); + $ret = Client::post($url, null, $headers, $this->proxy->makeReqOpt()); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } @@ -777,7 +789,7 @@ public function fetch($url, $bucket, $key = null) $ak = $this->auth->getAccessKey(); - list($ioHost, $err) = $this->config->getIovipHostV2($ak, $bucket); + list($ioHost, $err) = $this->config->getIovipHostV2($ak, $bucket, $this->proxy->makeReqOpt()); if ($err != null) { return array(null, $err); } @@ -879,7 +891,7 @@ public function prefetch($bucket, $key) $path = '/prefetch/' . $resource; $ak = $this->auth->getAccessKey(); - list($ioHost, $err) = $this->config->getIovipHostV2($ak, $bucket); + list($ioHost, $err) = $this->config->getIovipHostV2($ak, $bucket, $this->proxy->makeReqOpt()); if ($err != null) { return array(null, $err); @@ -1019,7 +1031,11 @@ public function setObjectLifecycleWithCond( private function rsfGet($bucket, $path) { - list($host, $err) = $this->config->getRsfHostV2($this->auth->getAccessKey(), $bucket); + list($host, $err) = $this->config->getRsfHostV2( + $this->auth->getAccessKey(), + $bucket, + $this->proxy->makeReqOpt() + ); if ($err != null) { return array(null, $err); @@ -1030,7 +1046,11 @@ private function rsfGet($bucket, $path) private function rsGet($bucket, $path) { - list($host, $err) = $this->config->getRsHostV2($this->auth->getAccessKey(), $bucket); + list($host, $err) = $this->config->getRsHostV2( + $this->auth->getAccessKey(), + $bucket, + $this->proxy->makeReqOpt() + ); if ($err != null) { return array(null, $err); @@ -1041,7 +1061,11 @@ private function rsGet($bucket, $path) private function rsPost($bucket, $path, $body = null) { - list($host, $err) = $this->config->getRsHostV2($this->auth->getAccessKey(), $bucket); + list($host, $err) = $this->config->getRsHostV2( + $this->auth->getAccessKey(), + $bucket, + $this->proxy->makeReqOpt() + ); if ($err != null) { return array(null, $err); @@ -1052,7 +1076,11 @@ private function rsPost($bucket, $path, $body = null) private function apiGet($bucket, $path) { - list($host, $err) = $this->config->getApiHostV2($this->auth->getAccessKey(), $bucket); + list($host, $err) = $this->config->getApiHostV2( + $this->auth->getAccessKey(), + $bucket, + $this->proxy->makeReqOpt() + ); if ($err != null) { return array(null, $err); @@ -1064,7 +1092,11 @@ private function apiGet($bucket, $path) private function apiPost($bucket, $path, $body = null) { - list($host, $err) = $this->config->getApiHostV2($this->auth->getAccessKey(), $bucket); + list($host, $err) = $this->config->getApiHostV2( + $this->auth->getAccessKey(), + $bucket, + $this->proxy->makeReqOpt() + ); if ($err != null) { return array(null, $err); @@ -1088,7 +1120,7 @@ private function ucPost($path, $body = null) private function getV2($url) { $headers = $this->auth->authorizationV2($url, 'GET', null, 'application/x-www-form-urlencoded'); - $ret = Client::get($url, $headers); + $ret = Client::get($url, $headers, $this->proxy->makeReqOpt()); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } @@ -1098,7 +1130,7 @@ private function getV2($url) private function postV2($url, $body) { $headers = $this->auth->authorizationV2($url, 'POST', $body, 'application/x-www-form-urlencoded'); - $ret = Client::post($url, $body, $headers); + $ret = Client::post($url, $body, $headers, $this->proxy->makeReqOpt()); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } diff --git a/src/Qiniu/Storage/FormUploader.php b/src/Qiniu/Storage/FormUploader.php index 4750cecb..d68654d8 100644 --- a/src/Qiniu/Storage/FormUploader.php +++ b/src/Qiniu/Storage/FormUploader.php @@ -62,7 +62,7 @@ public static function put( return array(null, $err); } - list($upHost, $err) = $config->getUpHostV2($accessKey, $bucket); + list($upHost, $err) = $config->getUpHostV2($accessKey, $bucket, $reqOpt); if ($err != null) { return array(null, $err); } @@ -134,7 +134,7 @@ public static function putFile( return array(null, $err); } - list($upHost, $err) = $config->getUpHostV2($accessKey, $bucket); + list($upHost, $err) = $config->getUpHostV2($accessKey, $bucket, $reqOpt); if ($err != null) { return array(null, $err); } diff --git a/src/Qiniu/Storage/ResumeUploader.php b/src/Qiniu/Storage/ResumeUploader.php index 4eea166c..00e88ef2 100644 --- a/src/Qiniu/Storage/ResumeUploader.php +++ b/src/Qiniu/Storage/ResumeUploader.php @@ -98,7 +98,7 @@ public function __construct( return array(null, $err); } - list($upHost, $err) = $config->getUpHostV2($accessKey, $bucket); + list($upHost, $err) = $config->getUpHostV2($accessKey, $bucket, $reqOpt); if ($err != null) { throw new \Exception($err->message(), 1); } @@ -212,7 +212,7 @@ private function uploadV1($fname, $blkputRets = null) if ($err != null) { return array(null, $err); } - list($upHostBackup, $err) = $this->config->getUpBackupHostV2($accessKey, $bucket); + list($upHostBackup, $err) = $this->config->getUpBackupHostV2($accessKey, $bucket, $this->reqOpt); if ($err != null) { return array(null, $err); } @@ -335,7 +335,7 @@ private function uploadV2($fname, $blkputRets = null) if ($err != null) { return array(null, $err); } - list($upHostBackup, $err) = $this->config->getUpBackupHostV2($accessKey, $bucket); + list($upHostBackup, $err) = $this->config->getUpBackupHostV2($accessKey, $bucket, $this->reqOpt); if ($err != null) { return array(null, $err); } diff --git a/src/Qiniu/Zone.php b/src/Qiniu/Zone.php index 655dc590..50d60c68 100644 --- a/src/Qiniu/Zone.php +++ b/src/Qiniu/Zone.php @@ -45,8 +45,14 @@ public static function qvmZonez1() return parent::qvmRegionHuabei(); } - public static function queryZone($ak, $bucket, $ucHost = null, $backupUcHosts = array(), $retryTimes = 2) - { - return parent::queryRegion($ak, $bucket, $ucHost, $backupUcHosts, $retryTimes); + public static function queryZone( + $ak, + $bucket, + $ucHost = null, + $backupUcHosts = array(), + $retryTimes = 2, + $reqOpt = null + ) { + return parent::queryRegion($ak, $bucket, $ucHost, $backupUcHosts, $retryTimes, $reqOpt); } } diff --git a/tests/Qiniu/Tests/FormUpTest.php b/tests/Qiniu/Tests/FormUpTest.php index 9e3dacc6..f75794ef 100755 --- a/tests/Qiniu/Tests/FormUpTest.php +++ b/tests/Qiniu/Tests/FormUpTest.php @@ -3,6 +3,7 @@ use PHPUnit\Framework\TestCase; +use Qiniu\Http\RequestOptions; use Qiniu\Storage\BucketManager; use Qiniu\Storage\FormUploader; use Qiniu\Storage\UploadManager; @@ -57,6 +58,24 @@ public function testData() $this->assertNotNull($ret['hash']); } + public function testDataWithProxy() + { + $key = self::getObjectKey('formput'); + $token = self::$auth->uploadToken(self::$bucketName); + list($ret, $error) = FormUploader::put( + $token, + $key, + 'hello world', + self::$cfg, + null, + 'text/plain', + null, + $this->makeReqOpt() + ); + $this->assertNull($error); + $this->assertNotNull($ret['hash']); + } + public function testData2() { $key = self::getObjectKey('formput'); @@ -67,11 +86,37 @@ public function testData2() $this->assertNotNull($ret['hash']); } + public function testData2WithProxy() + { + $key = self::getObjectKey('formput'); + $upManager = new UploadManager(); + $token = self::$auth->uploadToken(self::$bucketName); + list($ret, $error) = $upManager->put( + $token, + $key, + 'hello world', + null, + 'text/plain', + null, + $this->makeReqOpt() + ); + $this->assertNull($error); + $this->assertNotNull($ret['hash']); + } + public function testDataFailed() { $key = self::getObjectKey('formput'); $token = self::$auth->uploadToken('fakebucket'); - list($ret, $error) = FormUploader::put($token, $key, 'hello world', self::$cfg, null, 'text/plain', null); + list($ret, $error) = FormUploader::put( + $token, + $key, + 'hello world', + self::$cfg, + null, + 'text/plain', + null + ); $this->assertNull($ret); $this->assertNotNull($error); } @@ -80,7 +125,32 @@ public function testFile() { $key = self::getObjectKey('formPutFile'); $token = self::$auth->uploadToken(self::$bucketName, $key); - list($ret, $error) = FormUploader::putFile($token, $key, __file__, self::$cfg, null, 'text/plain', null); + list($ret, $error) = FormUploader::putFile( + $token, + $key, + __file__, + self::$cfg, + null, + 'text/plain', + null + ); + $this->assertNull($error); + $this->assertNotNull($ret['hash']); + } + + public function testFileWithProxy() + { + $key = self::getObjectKey('formPutFile'); + $token = self::$auth->uploadToken(self::$bucketName, $key); + list($ret, $error) = FormUploader::putFile( + $token, + $key, + __file__, + self::$cfg, + null, + 'text/plain', + $this->makeReqOpt() + ); $this->assertNull($error); $this->assertNotNull($ret['hash']); } @@ -95,6 +165,27 @@ public function testFile2() $this->assertNotNull($ret['hash']); } + public function testFile2WithProxy() + { + $key = self::getObjectKey('formPutFile'); + $token = self::$auth->uploadToken(self::$bucketName, $key); + $upManager = new UploadManager(); + list($ret, $error) = $upManager->putFile( + $token, + $key, + __file__, + null, + 'text/plain', + false, + null, + 'v1', + Config::BLOCK_SIZE, + $this->makeReqOpt() + ); + $this->assertNull($error); + $this->assertNotNull($ret['hash']); + } + public function testFileFailed() { $key = self::getObjectKey('fakekey'); @@ -103,4 +194,12 @@ public function testFileFailed() $this->assertNull($ret); $this->assertNotNull($error); } + + private function makeReqOpt() + { + $reqOpt = new RequestOptions(); + $reqOpt->proxy = 'socks5://127.0.0.1:8080'; + $reqOpt->proxy_user_password = 'user:pass'; + return $reqOpt; + } } diff --git a/tests/Qiniu/Tests/HttpTest.php b/tests/Qiniu/Tests/HttpTest.php index 52fbe029..c122f8e5 100755 --- a/tests/Qiniu/Tests/HttpTest.php +++ b/tests/Qiniu/Tests/HttpTest.php @@ -97,6 +97,18 @@ public function testPostTimeout() $this->assertEquals(-1, $response->statusCode); } + public function testSocks5Proxy() + { + $reqOpt = new RequestOptions(); + $reqOpt->proxy = 'socks5://localhost:8080'; + $response = Client::post('qiniu.com', null, array(), $reqOpt); + $this->assertEquals(-1, $response->statusCode); + + $reqOpt->proxy_user_password = 'user:pass'; + $response = Client::post('qiniu.com', null, array(), $reqOpt); + $this->assertEquals(200, $response->statusCode); + } + public function testPut() { $response = Client::PUT('uc.qbox.me/bucketTagging', null); diff --git a/tests/Qiniu/Tests/ResumeUpTest.php b/tests/Qiniu/Tests/ResumeUpTest.php index 0e2ed202..6feee55d 100755 --- a/tests/Qiniu/Tests/ResumeUpTest.php +++ b/tests/Qiniu/Tests/ResumeUpTest.php @@ -3,14 +3,11 @@ use PHPUnit\Framework\TestCase; -use phpDocumentor\Reflection\DocBlock\Tags\Version; -use Qiniu\Region; +use Qiniu\Http\RequestOptions; use Qiniu\Storage\BucketManager; -use Qiniu\Storage\ResumeUploader; use Qiniu\Storage\UploadManager; use Qiniu\Http\Client; use Qiniu\Config; -use Qiniu\Zone; class ResumeUpTest extends TestCase { @@ -106,6 +103,37 @@ public function test4ML2() unlink($tempFile); } + public function test4ML2WithProxy() + { + $key = self::getObjectKey('resumePutFile4ML_'); + $cfg = new Config(); + $upManager = new UploadManager($cfg); + $token = self::$auth->uploadToken(self::$bucketName, $key); + $tempFile = qiniuTempFile(4 * 1024 * 1024 + 10); + $resumeFile = tempnam(sys_get_temp_dir(), 'resume_file'); + $this->assertNotFalse($resumeFile); + list($ret, $error) = $upManager->putFile( + $token, + $key, + $tempFile, + null, + 'application/octet-stream', + false, + $resumeFile, + 'v2', + Config::BLOCK_SIZE, + $this->makeReqOpt() + ); + $this->assertNull($error); + $this->assertNotNull($ret['hash']); + + $domain = getenv('QINIU_TEST_DOMAIN'); + $response = Client::get("http://$domain/$key"); + $this->assertEquals(200, $response->statusCode); + $this->assertEquals(md5_file($tempFile, true), md5($response->body(), true)); + unlink($tempFile); + } + // public function test8M() // { // $key = 'resumePutFile8M'; @@ -315,4 +343,12 @@ public function testResumeUploadWithInvalidVersion() } $this->assertEquals(count($testInvalidVersions), $expectExceptionCount); } + + private function makeReqOpt() + { + $reqOpt = new RequestOptions(); + $reqOpt->proxy = 'socks5://127.0.0.1:8080'; + $reqOpt->proxy_user_password = 'user:pass'; + return $reqOpt; + } } diff --git a/tests/socks5-server/go.mod b/tests/socks5-server/go.mod new file mode 100644 index 00000000..1efbec2c --- /dev/null +++ b/tests/socks5-server/go.mod @@ -0,0 +1,7 @@ +module github.com/qiniu/php-socks5-server + +go 1.21.0 + +require github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 + +require golang.org/x/net v0.14.0 // indirect diff --git a/tests/socks5-server/go.sum b/tests/socks5-server/go.sum new file mode 100644 index 00000000..cd9009f3 --- /dev/null +++ b/tests/socks5-server/go.sum @@ -0,0 +1,4 @@ +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= diff --git a/tests/socks5-server/main.go b/tests/socks5-server/main.go new file mode 100644 index 00000000..7df77fb3 --- /dev/null +++ b/tests/socks5-server/main.go @@ -0,0 +1,24 @@ +package main + +import ( + "log" + "os" + + socks5 "github.com/armon/go-socks5" +) + +func main() { + config := socks5.Config{ + AuthMethods: []socks5.Authenticator{socks5.UserPassAuthenticator{Credentials: socks5.StaticCredentials{"user": "pass"}}}, + Logger: log.New(os.Stderr, "", log.LstdFlags|log.LUTC|log.Lshortfile), + } + + server, err := socks5.New(&config) + if err != nil { + panic(err) + } + + if err = server.ListenAndServe("tcp", "127.0.0.1:8080"); err != nil { + panic(err) + } +}