GetCpolar留V3版去掉V2版

GetCpolar留V3版去掉V2版

php 复制代码
class GetCpolarV3
{
    private static $baseUrl = "http://localhost:9200";
    private string $token; //为了减少重复获取token的次数,使用静态变量缓存token
    public string $response;//tunnels的响应字符串
    public int $lastUpdateTimestamp; //最近更新时间戳
    public array $cpolarInfo;//解析后的Cpolar信息数组
    private CurlShareHandle $sh; // cURL共享句柄
    
    function __construct() {
        $this->sh = curl_share_init();
        curl_share_setopt($this->sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
    }
    function __destruct() {
        curl_share_close($this->sh);
    }
    /**
     * 
     * 获取认证token
     */
    private function getToken(string $varname = 'cpolarloginaccount') {
        $url = self::$baseUrl . "/api/v1/user/login";
        
        $credentials = varjpandorabox($varname);    //pandorabox.php
        $credentialsData = json_decode($credentials->data, true);
        $loginData = [
            "email" => $credentialsData['email'] ?? '',
            "password" => $credentialsData['password'] ?? ''
        ];
        
        
        $jsonContent = json_encode($loginData);
        
        // 初始化第一个 cURL 句柄,并将它设置到共享句柄
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SHARE, $this->sh);

        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $jsonContent,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                "Content-Type: application/json",
                "Content-Length: " . strlen($jsonContent)
            ],
            CURLOPT_TIMEOUT => 30
        ]);
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        //curl_close($ch);    //Function curl_close() is deprecated since 8.5, as it has no effect since PHP 8.0
        curl_reset($ch); // 重置 cURL 句柄以便复用
        
        if ($error) {
            throw new Exception("cURL Error: " . $error);
        }
        
        if ($httpCode >= 400) {
            throw new Exception("HTTP Error: " . $httpCode);
        }
        
        $responseData = json_decode($response, true);
        
        if (!isset($responseData['data']['token'])) {
            throw new Exception("Token not found in response");
        }
        
        $this->token = $responseData['data']['token'];
    }
    /**
     * 
     * 使用token等敏感信息获取隧道列表
     */
    public function getTunnels()
    {
        if (empty($this->token)==true) {
            $this->getToken();
        }
        //echo "Using token: " . $this->token . "\n";
        $url = self::$baseUrl . "/api/v1/tunnels";
        //echo "Fetching tunnels from: " . $url . "\n";

        // 初始化第一个 cURL 句柄,并将它设置到共享句柄
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SHARE, $this->sh);

        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                "Authorization: Bearer " . $this->token,
                "Content-Type: application/json"
            ],
            CURLOPT_TIMEOUT => 10
        ]);
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        //curl_close($ch);    //Function curl_close() is deprecated since 8.5, as it has no effect since PHP 8.0
        curl_reset($ch); // 重置 cURL 句柄以便复用

        if ($error) {
            throw new Exception("cURL Error: " . $error);
        }
        
        if ($httpCode >= 400) {
            throw new Exception("HTTP Error: " . $httpCode);
        }
        
        return $this->response = $response;
    } 
    /**
     * 
     * 
     * 从JSON字符串解析Cpolar信息
     */
    public function getCpolarInfoFromJsonString(string $response) 
    {
        $cpolarInfo = [
            'total' => 0,
            'items' => []
        ];
        
        $data = json_decode($response, true);
        
        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new Exception("JSON parse error: " . json_last_error_msg());
        }
        
        if (!isset($data['data']['items'])) {
            throw new Exception("Invalid JSON structure");
        }
        
        $cpolarInfo['total'] = $data['data']['total'] ?? 0;
        $items = $data['data']['items'];
        
        foreach ($items as $item) {
            $name = $item['name'] ?? '';
            $public_url = $item['public_url'] ?? '';
            $create_datetime = '';
            
            // 处理publish_tunnels数组
            if (isset($item['publish_tunnels']) && is_array($item['publish_tunnels'])) {
                foreach ($item['publish_tunnels'] as $tunnel) {
                    $create_datetime = $tunnel['create_datetime'] ?? '';
                    break; // 只取第一个tunnel
                }
            }
            
            // 替换协议
            $newUrl = str_replace('tls://', 'https://', $public_url);
            
            $cpolarInfo['items'][] = [
                'name' => $name,
                'create_datetime' => $create_datetime,
                'pubulic_url' => $newUrl
            ];
        }
        
        $this->cpolarInfo = $cpolarInfo;
        return $this->cpolarInfo;
    }  
    
    public function getCpolarInfoS()
    {
        $this->getTunnels();
        $this->lastUpdateTimestamp = time();//// 当前 Unix 时间戳(秒)
        return $this->getCpolarInfoFromJsonString($this->response);
    }
}
php 复制代码
class GetCpolarV2
{
    private static $baseUrl = "http://localhost:9200";
    private string $token; //为了减少重复获取token的次数,使用静态变量缓存token
    private CurlHandle $ch; // cURL共享句柄

    public int $lastUpdateTimestamp; //最近更新时间戳

    function __construct() {
        $this->ch = curl_init();
    }
    /**
     * 
     * 获取认证token
     */
    private function getToken(string $varname = 'cpolarloginaccount') {
        $url = self::$baseUrl . "/api/v1/user/login";
        
        $credentials = varjpandorabox($varname);    //pandorabox.php
        $credentialsData = json_decode($credentials->data, true);
        $loginData = [
            "email" => $credentialsData['email'] ?? '',
            "password" => $credentialsData['password'] ?? ''
        ];
        
        
        $jsonContent = json_encode($loginData);
        
        // 初始化第一个 cURL 句柄
        //$ch = curl_init();
        curl_reset($this->ch); // 重置 cURL 句柄以便复用
        curl_setopt_array($this->ch, [
            CURLOPT_URL => $url,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $jsonContent,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                "Content-Type: application/json",
                "Content-Length: " . strlen($jsonContent)
            ],
            CURLOPT_TIMEOUT => 30
        ]);
        
        $response = curl_exec($this->ch);
        //$httpCode = curl_getinfo($this->ch, CURLINFO_HTTP_CODE);
       // $error = curl_error($this->ch);
        //curl_close($this->ch);    //Function curl_close() is deprecated since 8.5, as it has no effect since PHP 8.0
        curl_reset($this->ch); // 重置 cURL 句柄以便复用
        
        // if ($error) {
        //     throw new Exception("cURL Error: " . $error);
        // }
        
        // if ($httpCode >= 400) {
        //     throw new Exception("HTTP Error: " . $httpCode);
        // }
        
        $responseData = json_decode($response, true);
        
        if (!isset($responseData['data']['token'])) {
            throw new Exception("Token not found in response");
        }
        
        $this->token = $responseData['data']['token'];
    }

    /**
     * 
     * 使用token等敏感信息获取隧道列表
     */
    public function getTunnels()
    {
        if (empty($this->token)==true) {
            $this->getToken();
        }
        //echo "Using token: " . $this->token . "\n";
        $url = self::$baseUrl . "/api/v1/tunnels";
        //echo "Fetching tunnels from: " . $url . "\n";

        //$ch = curl_init();
        curl_reset($this->ch); // 重置 cURL 句柄以便复用
        curl_setopt_array($this->ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                "Authorization: Bearer " . $this->token,
                "Content-Type: application/json"
            ],
            CURLOPT_TIMEOUT => 10
        ]);
        
        $response = curl_exec($this->ch);
        //$httpCode = curl_getinfo($this->ch, CURLINFO_HTTP_CODE);
        //$error = curl_error($this->ch);
        //curl_close($this->ch);    //Function curl_close() is deprecated since 8.5, as it has no effect since PHP 8.0
        curl_reset($this->ch); // 重置 cURL 句柄以便复用

        // if ($error) {
        //     throw new Exception("cURL Error: " . $error);
        // }
        
        // if ($httpCode >= 400) {
        //     throw new Exception("HTTP Error: " . $httpCode);
        // }
        
        return $response;
    } 
    public function getCpolarInfoS()
    {
        $res = $this->getTunnels();
        $this->lastUpdateTimestamp = time();//// 当前 Unix 时间戳(秒)
        return DynamicCpolar::getCpolarInfoFromJsonString($res);
    }
}
php 复制代码
final class GetCpolarV4
{
    private const BASE = 'http://localhost:9200';
    private static ?string $token = null;
    private static int $tokenAt = 0;
    private const TOKEN_TTL = 72000; // 20h

    private CurlHandle $ch;
    public string $response = '';
    public array $cpolarInfo = [];
    public int $lastUpdateTimestamp = 0;

    public function __construct() {
        $this->ch = curl_init();
        // 只设一次"永不改变"的选项,之后用 CURLOPT_URL / HTTPHEADER 覆盖可变部分
        curl_setopt_array($this->ch, [
            CURLOPT_RETURNTRANSFER => true,   // ← 关键:只设一次,绝不被 reset 清掉
            CURLOPT_TIMEOUT        => 15,
            CURLOPT_CONNECTTIMEOUT => 5,
            CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
            // 注意:这里【不要】curl_reset(),reset 会把上面全清了
        ]);
    }

    private function exec(string $method, string $path, ?array $body = null, ?string $bearer = null): array
    {
        curl_setopt_array($this->ch, [
            CURLOPT_URL           => self::BASE . $path,
            CURLOPT_CUSTOMREQUEST => $method,
            CURLOPT_POSTFIELDS    => $body ? json_encode($body, JSON_UNESCAPED_SLASHES) : null,
            CURLOPT_HTTPHEADER    => array_filter([
                'Content-Type: application/json',
                $bearer ? 'Authorization: Bearer ' . $bearer : null,
            ]),
        ]);

        $raw  = curl_exec($this->ch);
        $code = curl_getinfo($this->ch, CURLINFO_HTTP_CODE);
        $err  = curl_error($this->ch);
        $errno= curl_errno($this->ch);

        if ($raw === false || $errno !== 0) {
            throw new RuntimeException("cURL({$errno}): {$err} @ {$path}");
        }
        if ($code >= 400) {
            throw new RuntimeException("HTTP {$code} @ {$path}: " . mb_substr((string)$raw, 0, 200));
        }
        $j = json_decode($raw, true);
        if (!is_array($j)) {
            throw new RuntimeException("Bad JSON({$code}) @ {$path}: " . mb_substr($raw, 0, 200));
        }
        return $j;
    }

    private function token(): string
    {
        if (self::$token !== null && time() - self::$tokenAt < self::TOKEN_TTL) {
            return self::$token;
        }
        $c = json_decode(varjpandorabox('cpolarloginaccount')->data ?? '{}', true);
        $j = $this->exec('POST', '/api/v1/user/login', [
            'email' => $c['email'] ?? '', 'password' => $c['password'] ?? ''
        ]);
        if (!isset($j['data']['token'])) {
            throw new RuntimeException('Token not found: ' . json_encode($j, JSON_UNESCAPED_UNICODE));
        }
        self::$token   = $j['data']['token'];
        self::$tokenAt = time();
        return self::$token;
    }

    public function getCpolarInfoS(): array
    {
        $j = $this->exec('GET', '/api/v1/tunnels', null, $this->token());
        $this->lastUpdateTimestamp = time();
        $this->response = json_encode($j);

        $items = [];
        foreach (($j['data']['items'] ?? []) as $it) {
            $ts = '';
            foreach (($it['publish_tunnels'] ?? []) as $t) { $ts = $t['create_datetime'] ?? ''; break; }
            $items[] = [
                'name'            => $it['name'] ?? '',
                'create_datetime' => $ts,
                'created_at_ts'   => $ts ? (strtotime($ts) ?: 0) : 0,   // ← V5 pick() 直接吃
                'public_url'      => str_replace(['tls://','tcp://'], ['https://','http://'], $it['public_url'] ?? ''),
            ];
        }
        return $this->cpolarInfo = ['total' => $j['data']['total'] ?? count($items), 'items' => $items];
    }
}
php 复制代码
    /**
     *
     */
    public static function checkHttpsDomain(int $timeout = 2): bool
    {
        $token = self::getToken();

        $url = self::$baseUrl . "/api/v1/tunnels";
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                "Authorization: Bearer " . $token,
                "Content-Type: application/json"
            ],
            CURLOPT_TIMEOUT => $timeout
        ]);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $errno = curl_errno($ch);
        //echo $response."\n";
        if($response=='' || empty($response)){return false;}
        $cp = json_decode($response,true);
        //var_dump($cp);
        if(!isset($cp['data']['items']) && isset($cp['data'])){return false;}
        $exist = false;
        foreach($cp['data']['items'] as $it)
        {
            if($it['name'] == 'Apache' && key_exists('status', $it)){ //key_exists同时判断 key 存在 + value 不为 null   
                 if($it['status'] == 'active'){$exist=true;}
                 //echo $exist.PHP_EOL;
            }
           
        }
        
        return $exist == true && $errno === 0 && $httpCode >= 200 && $httpCode < 400;
    }   
相关推荐
FYKJ_20104 小时前
springboot同人周边订单管理系统48955-计算机毕业设计、课程设计
java·javascript·vue.js·spring boot·django·php·课程设计
火云代理16 小时前
更换网络后为什么会退出登录?分清 IP、Cookie 与会话的关系
服务器·网络·网络协议·tcp/ip·php·ip
火云代理20 小时前
同一个网站,有的网络能打开、有的打不开?认识 IPv4 与 IPv6 的访问差异
服务器·网络·网络协议·tcp/ip·测试工具·php·状态模式
笑容掩饰我的失落1 天前
区块链从小白到精通(七):Solidity 语法精讲——数据类型、函数、修饰器与事件
算法·区块链·php·智能合约·哈希算法
笑容掩饰我的失落2 天前
区块链从小白到精通(八):从零实现一个标准 ERC-20 代币(完整可运行代码)
算法·区块链·php·智能合约·哈希算法
xbzb3 天前
从零容器化部署 ECShop:Harbor 私有仓库 + 自定义 PHP 镜像 + LNMP 三容器
容器·php·harbor·镜像·仓库·ecshop
爱和冰阔落4 天前
【Linux网络】JsonCpp 怎么实现序列化?从 Request/Response 到网络计算器消息设计
linux·运维·网络·php
eggwyw4 天前
PHP8.5怎么用ffmpeg提取视频里的字幕轨道
开发语言·php
我叫黑大帅5 天前
PHP 常驻 Worker 中 MySQL 连接中断问题报告
后端·面试·php