diff --git a/app/Libraries/MySocket/Cloudflare/CloudflareClient.php b/app/Libraries/MySocket/Cloudflare/CloudflareClient.php deleted file mode 100644 index f14409b..0000000 --- a/app/Libraries/MySocket/Cloudflare/CloudflareClient.php +++ /dev/null @@ -1,54 +0,0 @@ -request('GET', $uri, $options); - } - public function post($uri, array $options = []): ResponseInterface - { - return $this->request('POST', $uri, $options); - } - public function put($uri, array $options = []): ResponseInterface - { - return $this->request('PUT', $uri, $options); - } - public function patch($uri, array $options = []): ResponseInterface - { - return $this->request('PATCH', $uri, $options); - } - public function delete($uri, array $options = []): ResponseInterface - { - return $this->request('DELETE', $uri, $options); - } - - public function request(string $method, $uri = '', array $options = []): ResponseInterface - { - if (self::$_request >= self::$_request_max) { - log_message('warning', sprintf("--Cloudflare API Call %s초 대기 시작--", self::$_request_timewait)); - sleep(intval(self::$_request_timewait)); - self::$_request = 0; - log_message('warning', sprintf("--Cloudflare API Call %s초 대기 종료--", self::$_request_timewait)); - } - self::$_request++; - $requestOptions = []; - $requestOptions[in_array($method, ['get', 'getAsync']) ? 'query' : 'json'] = $options; - return parent::request($method, $uri, $requestOptions); - } -} diff --git a/app/Libraries/MySocket/Cloudflare/RecordSocket.php b/app/Libraries/MySocket/Cloudflare/RecordSocket.php index 4e80830..43ee0f3 100644 --- a/app/Libraries/MySocket/Cloudflare/RecordSocket.php +++ b/app/Libraries/MySocket/Cloudflare/RecordSocket.php @@ -59,7 +59,7 @@ class RecordSocket extends CloudflareSocket 'content' => $content, 'proxied' => $proxied === 'on' ? true : false ]; - $cf = $this->getClient()->post("zones/{$this->_zone_entity->getPK()}/dns_records", $datas); + $cf = $this->post("zones/{$this->_zone_entity->getPK()}/dns_records", $datas); $cf = json_decode($cf->getBody()); if (!$cf->success) { $message = "Record:" . __FUNCTION__ . "에서 실패:\nrequest:" . var_export($datas, true) . "\nresponse:" . var_export($cf, true); @@ -91,7 +91,7 @@ class RecordSocket extends CloudflareSocket } // 인코딩된 JSON을 확인 // throw new \Exception("Record:" . __FUNCTION__ . "\n" . json_encode($datas, JSON_PRETTY_PRINT) . "\n" . var_export($datas, true)); - $cf = $this->getClient()->put("zones/{$this->_zone_entity->getPK()}/dns_records/{$entity->getPK()}", $datas); + $cf = $this->put("zones/{$this->_zone_entity->getPK()}/dns_records/{$entity->getPK()}", $datas); $cf = json_decode($cf->getBody()); if (!$cf->success) { $message = "Record:" . __FUNCTION__ . "에서 실패:\nrequest:" . var_export($datas, true) . "\nresponse:" . var_export($cf, true); @@ -104,7 +104,7 @@ class RecordSocket extends CloudflareSocket } public function delete(RecordEntity $entity): void { - $cf = $this->getClient()->delete("zones/{$this->_zone_entity->getPK()}/dns_records/{$entity->getPK()}"); + $cf = $this->delete("zones/{$this->_zone_entity->getPK()}/dns_records/{$entity->getPK()}"); $cf = json_decode($cf->getBody()); if (!$cf->success) { $message = "Record:" . __FUNCTION__ . "에서 실패:\nresponse:" . var_export($cf, true); @@ -118,7 +118,7 @@ class RecordSocket extends CloudflareSocket public function sync(RecordEntity $entity): void { // 기존 Sync형태 - $cf = $this->getClient()->get("zones/{$this->_zone_entity->getPK()}/dns_records/{$entity->getPK()}"); + $cf = $this->get("zones/{$this->_zone_entity->getPK()}/dns_records/{$entity->getPK()}"); $cf = json_decode($cf->getBody()); if (!$cf->success) { $message = "Record:" . __FUNCTION__ . "에서 실패:\nresponse:" . var_export($cf, true); @@ -129,7 +129,7 @@ class RecordSocket extends CloudflareSocket log_message("debug", var_export($cf->result, true)); $entity = $this->getModel()->modify($entity, $this->getArrayByResult($cf->result)); //Async형태 - // $promise = $this->getClient()->getAsync("zones/{$this->_zone_entity->getPK()}/dns_records/{$entity->getPK()}"); + // $promise = $this->getAsync("zones/{$this->_zone_entity->getPK()}/dns_records/{$entity->getPK()}"); // $promise->then( // onFulfilled: function ($response) use ($entity): RecordEntity { // $record = json_decode($response->getBody(), true)['result']; diff --git a/app/Libraries/MySocket/Cloudflare/ZoneSocket.php b/app/Libraries/MySocket/Cloudflare/ZoneSocket.php index 744c7f4..7b4035c 100644 --- a/app/Libraries/MySocket/Cloudflare/ZoneSocket.php +++ b/app/Libraries/MySocket/Cloudflare/ZoneSocket.php @@ -60,7 +60,7 @@ class ZoneSocket extends CloudflareSocket //Cfzone에서 가져온 값을 zone에 setting private function getCFSetting(ZoneEntity $entity): array { - $cf = $this->getClient()->get('zones/' . $entity->getPK() . '/settings'); + $cf = $this->get('zones/' . $entity->getPK() . '/settings'); $cf = json_decode($cf->getBody()); if (!$cf->success) { $message = "Zone:" . __FUNCTION__ . "에서 실패:\nresponse:" . var_export($cf, true); @@ -78,7 +78,7 @@ class ZoneSocket extends CloudflareSocket private function setCFSetting(ZoneEntity $entity, string $field, string $value): string { $datas = ['value' => $value]; - $cf = $this->getClient()->patch('zones/' . $entity->getPK() . '/settings/' . $field, $datas); + $cf = $this->patch('zones/' . $entity->getPK() . '/settings/' . $field, $datas); $cf = json_decode($cf->getBody()); if (!$cf->success || $cf->result->id !== $field) { $message = "Zone:" . __FUNCTION__ . "에서 실패:\nrequest:" . var_export($datas, true) . "\nresponse:" . var_export($cf, true); @@ -97,7 +97,7 @@ class ZoneSocket extends CloudflareSocket 'name' => $domain, 'jump_start' => $jump_start, ]; - $cf = $this->getClient()->post('zones/', $datas); + $cf = $this->post('zones/', $datas); $cf = json_decode($cf->getBody()); if (!$cf->success) { $message = "Zone:" . __FUNCTION__ . "에서 실패:\nrequest:" . var_export($datas, true) . "\nresponse:" . var_export($cf, true); @@ -128,7 +128,7 @@ class ZoneSocket extends CloudflareSocket } public function delete(ZoneEntity $entity): void { - $cf = $this->getClient()->delete("zones/{$entity->getPK()}"); + $cf = $this->delete("zones/{$entity->getPK()}"); $cf = json_decode($cf->getBody()); if (!$cf->success) { $message = "Zone:" . __FUNCTION__ . "에서 실패:\nresponse:" . var_export($cf, true); @@ -141,7 +141,7 @@ class ZoneSocket extends CloudflareSocket } public function sync(ZoneEntity $entity): void { - $cf = $this->getClient()->get("zones/{$entity->getPK()}"); + $cf = $this->get("zones/{$entity->getPK()}"); $cf = json_decode($cf->getBody()); if (!$cf->success) { $message = "Zone:" . __FUNCTION__ . "에서 실패:\nresponse:" . var_export($cf, true); diff --git a/app/Libraries/MySocket/CloudflareSocket.php b/app/Libraries/MySocket/CloudflareSocket.php index bb68c30..c3cff14 100644 --- a/app/Libraries/MySocket/CloudflareSocket.php +++ b/app/Libraries/MySocket/CloudflareSocket.php @@ -2,39 +2,47 @@ namespace App\Libraries\MySocket; -use App\Libraries\CommonLibrary; -use App\Libraries\MySocket\Cloudflare\CloudflareClient; +use Psr\Http\Message\ResponseInterface; use App\Models\Cloudflare\AuthModel; use App\Models\Cloudflare\AccountModel; use App\Entities\Cloudflare\AuthEntity; -abstract class CloudflareSocket extends CommonLibrary +abstract class CloudflareSocket extends MySocket { + private static int $_request = 0; + private static int $_request_max = 1000; + private static int $_request_perpage_max = 700; + private static int $_request_timewait = 60; private $_authModel = null; private $_accountModel = null; - private $_client = null; private $_auth_entity = null; protected function __construct(AuthEntity $auth_entity) { - parent::__construct(); + parent::__construct([ + 'base_uri' => 'https://api.cloudflare.com/client/v4/', + 'headers' => [ + 'X-Auth-Email' => $this->_auth_entity->getID(), // 인증 토큰 사용 + 'X-Auth-Key' => $this->_auth_entity->getAuthKey(), // 인증 토큰 사용 + 'Content-Type' => 'application/json', + ] + ]); $this->_auth_entity = $auth_entity; + self::$_request_max = getenv("cfmgr.request.max") ?: 1000; + self::$_request_perpage_max = getenv("cfmgr.request.perpage.max") ?: 700; + self::$_request_timewait = getenv("cfmgr.request.timewait") ?: 60; } abstract protected function getArrayByResult($result, array $formDatas = []): array; - final protected function getClient(): CloudflareClient + + final public function request(string $method, $uri = '', array $options = []): ResponseInterface { - if ($this->_client === null) { - // Guzzle HTTP 클라이언트를 설정하면서 Cloudflare API 토큰 사용 - $this->_client = new CloudflareClient([ - 'base_uri' => 'https://api.cloudflare.com/client/v4/', - 'headers' => [ - 'X-Auth-Email' => $this->_auth_entity->getID(), // 인증 토큰 사용 - 'X-Auth-Key' => $this->_auth_entity->getAuthKey(), // 인증 토큰 사용 - 'Content-Type' => 'application/json', - ], - 'verify' => getenv("socket.web.ssl.verify") == "true" ? true : false, // SSL 인증서 검증을 비활성화 - ]); + if (self::$_request >= self::$_request_max) { + log_message('warning', sprintf("--Cloudflare API Call %s초 대기 시작--", self::$_request_timewait)); + sleep(intval(self::$_request_timewait)); + self::$_request = 0; + log_message('warning', sprintf("--Cloudflare API Call %s초 대기 종료--", self::$_request_timewait)); } - return $this->_client; + self::$_request++; + return parent::request($method, $uri, $options); } final protected function getAuthModel(): AuthModel { @@ -57,7 +65,7 @@ abstract class CloudflareSocket extends CommonLibrary do { $query = [ 'page' => $page, - 'per_page' => CloudflareClient::REQUEST_PERPAGE_MAX, + 'per_page' => self::$_request_perpage_max, 'match' => 'all', ]; $response = $this->getClient()->get($uri, $query); @@ -68,7 +76,7 @@ abstract class CloudflareSocket extends CommonLibrary throw new \Exception($message); } $results = array_merge($results, $cf->result); - if (count($cf->result) < CloudflareClient::REQUEST_PERPAGE_MAX) { + if (count($cf->result) < self::$_request_perpage_max) { break; } $page++; diff --git a/app/Libraries/MySocket/GoogleSocket.php b/app/Libraries/MySocket/GoogleSocket.php index 7df7c9d..8013563 100644 --- a/app/Libraries/MySocket/GoogleSocket.php +++ b/app/Libraries/MySocket/GoogleSocket.php @@ -2,31 +2,21 @@ namespace App\Libraries\MySocket; -use App\Libraries\CommonLibrary; +use GuzzleHttp\Client; -class GoogleSocket extends CommonLibrary +class GoogleSocket extends Google_Client { - private $_client = null; private $_session = null; private $_access_code = ""; public function __construct() { parent::__construct(); $this->_session = \Config\Services::session(); - } - - //Override - public function getClient(): Google_Client - { - if (is_null($this->_client)) { - $this->_client = new Google_Client(); - $this->_client->setClientId(getenv("socket.google.client.id")); - $this->_client->setClientSecret(getenv("socket.google.client.key")); - $this->_client->setRedirectUri(base_url() . getenv("socket.google.client.callback_url")); - $this->_client->addScope('email'); - $this->_client->addScope('profile'); - } - return $this->_client; + $this->setClientId(getenv("socket.google.client.id")); + $this->setClientSecret(getenv("socket.google.client.key")); + $this->setRedirectUri(base_url() . getenv("socket.google.client.callback_url")); + $this->addScope('email'); + $this->addScope('profile'); } public function getAccessCode(): string @@ -44,13 +34,13 @@ class GoogleSocket extends CommonLibrary public function setAccessToken() { //2.토큰정보 가져오기 - $tokenInfo = $this->getClient()->fetchAccessTokenWithAuthCode($this->getAccessCode()); + $tokenInfo = $this->fetchAccessTokenWithAuthCode($this->getAccessCode()); if (isset($tokenInfo['error'])) { throw new \Exception($tokenInfo['error']); } $token = $tokenInfo[getenv("socket.google.client.token_name")]; //3. Google Service에 접근하기위해 Access Token을 설정 - $this->getClient()->setAccessToken($token); + $this->setAccessToken($token); //4. Google에 로그인이 했으므로 세션에 Token값 설정 $this->_session->set(getenv("socket.google.client.token_name"), $token); } diff --git a/app/Libraries/MySocket/MySocket.php b/app/Libraries/MySocket/MySocket.php new file mode 100644 index 0000000..b2e55d0 --- /dev/null +++ b/app/Libraries/MySocket/MySocket.php @@ -0,0 +1,80 @@ +_cookieJar === null) { + $this->_cookieJar = new CookieJar(); + } + return $this->_cookieJar; + } + protected function getUserAgent(): string + { + // User-Agent 목록 배열 + $userAgents = [ + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15', + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0', + 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1', + 'Mozilla/5.0 (Linux; Android 10; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36' + ]; + return $userAgents[array_rand($userAgents)]; + } + protected function getRequestOptions(string $method, array $options = []): array + { + //cookies->쿠키값 , timeout->5초 안에 응답이 없으면 타임아웃 + $requestOptions = [ + 'cookies' => $this->getCookieJar(), + 'timeout' => getenv("socket.web.timeout"), + 'headers' => [ + 'User-Agent' => $this->getUserAgent(), + ], + ]; + return $requestOptions; + } + + public function get($uri, array $options = []): ResponseInterface + { + return $this->request('GET', $uri, $options); + } + public function post($uri, array $options = []): ResponseInterface + { + return $this->request('POST', $uri, $options); + } + public function put($uri, array $options = []): ResponseInterface + { + return $this->request('PUT', $uri, $options); + } + public function patch($uri, array $options = []): ResponseInterface + { + return $this->request('PATCH', $uri, $options); + } + public function delete($uri, array $options = []): ResponseInterface + { + return $this->request('DELETE', $uri, $options); + } + public function request(string $method, $uri = '', array $options = []): ResponseInterface + { + $requestOptions = $this->getRequestOptions($method, $options); + $requestOptions[in_array($method, ['get', 'getAsync']) ? 'query' : 'json'] = $options; + log_message("debug", __FUNCTION__ . + "=> 호출 Socket URL:{$uri}\n--------------\n" . + var_export($options, true) . + "\n--------------\n"); + return parent::request($method, $uri, $requestOptions); + } +} diff --git a/app/Libraries/MySocket/WebSocket.php b/app/Libraries/MySocket/WebSocket.php index 03b0754..76dcf11 100644 --- a/app/Libraries/MySocket/WebSocket.php +++ b/app/Libraries/MySocket/WebSocket.php @@ -2,89 +2,38 @@ namespace App\Libraries\MySocket; -use App\Libraries\CommonLibrary; -use GuzzleHttp\Cookie\CookieJar; -use GuzzleHttp\Client; +use Psr\Http\Message\ResponseInterface; -class WebSocket extends CommonLibrary +class WebSocket extends MySocket { private $_host = null; - private $_client = null; - private $_cookieJar = null; public function __construct(string $host) { parent::__construct(); $this->_host = $host; } - final public function getHost(): string + final public function getURL($uri): string { - return $this->_host; - } - - final public function getClient(): Client - { - if ($this->_client === null) { - $this->_client = new Client(['verify' => getenv("socket.web.ssl.verify") == "true" ? true : false]); + // url에 http 나 https가 포함되어 있지않으면 + if (!preg_match('~^(http|https)://~i', $uri)) { + $uri = "{$this->_host}{$uri}"; } - return $this->_client; + return $uri; } - - final protected function getCookieJar() + public function getResponse($uri, array $options = []): ResponseInterface { - if ($this->_cookieJar === null) { - $this->_cookieJar = new CookieJar(); + $response = parent::get($this->getURL($uri), $options); + if ($response->getStatusCode() != 200) { + throw new \Exception("error", __FUNCTION__ . + "=> {$uri} 접속실패: " . + $response->getStatusCode()); } - return $this->_cookieJar; + return $response; } - - //url에 http 나 https가 포함되어 있으면 true - final public function isContainsHttpOrHttps($url): bool + public function getContent(string $uri, array $options = []): string { - return strpos($url, 'http://') !== false || strpos($url, 'https://') !== false; - } - - public function getResponseOptions(string $type, array $options = []): array - { - switch ($type) { - case 'agent': - // User-Agent 목록 배열 - $userAgents = [ - 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36', - 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15', - 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0', - 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1', - 'Mozilla/5.0 (Linux; Android 10; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36' - ]; - // 배열에서 랜덤으로 하나의 User-Agent 선택 - $randomUserAgent = $userAgents[array_rand($userAgents)]; - $options['headers'] = [ - 'User-Agent' => $randomUserAgent, - ]; - break; - } - return $options; - } - public function getResponse(string $url, $method = "get", array $options = []): mixed - { - //url에 http 나 https가 포함되어 있지않으면 - if (!($this->isContainsHttpOrHttps($url))) { - $url = $this->gethost() . $url; - } - //기본 Option - $options['cookies'] = $this->getCookieJar(); //쿠키값 - $options['timeout'] = getenv("socket.web.timeout"); // 5초 안에 응답이 없으면 타임아웃 - log_message("debug", __FUNCTION__ . "=> 호출 Socket URL-> " . $url); - return $this->getClient()->$method($url, $options); - } - - public function getContent(string $url, $method = "get", array $options = []): string - { - log_message("debug", __FUNCTION__ . "=> 호출 URL:" . $url); - $response = $this->getResponse($url, $method, $options); - if ($response->getStatusCode() == 200) { - // return $response->getBody()->getContents(); - return $response->getBody(); - } - throw new \Exception("error", __FUNCTION__ . "=> {$url} 접속실패: " . $response->getStatusCode()); + $response = $this->getResponse($uri, $options); + // return $response->getBody()->getContents(); + return $response->getBody(); } }