/** * SakuraFrp API 客户端 * 仅实现了获取隧道列表的功能 * * @version 1.0 * @author AI Assistant */ class SakuraFrpApi { /** * API 基础 URL * @var string */ private const BASE_URL = 'https://api.natfrp.com/v4'; /** * 用户认证 Token * @var string */ private $userToken; /** * 构造函数 * @param string $userToken 您的 SakuraFrp 用户 Token */ public function __construct(string $userToken) { $this->userToken = $userToken; } /** * 获取隧道列表 * 对应 C# 中的 tunnels() 方法 * * @return array|null 成功时返回隧道列表数组,失败时返回 null * @throws Exception 如果请求失败或发生 cURL 错误 */ public function getTunnels(): ?array { $url = self::BASE_URL . '/tunnels'; //echo "请求 URL: " . $url . "\n"; return $this->makeRequest('GET', $url); } /** * 通用的请求方法 * * @param string $method HTTP 方法 (GET, POST, etc.) * @param string $url 请求的 URL * @param array|null $data 对于 POST 请求,要发送的 JSON 数据 * @return array|null 成功时返回解码后的 JSON 数组,失败时返回 null * @throws Exception */ private function makeRequest(string $method, string $url, ?array $data = null): ?array { // 1. 初始化 cURL $ch = curl_init(); // 2. 设置 cURL 选项 curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 将响应作为字符串返回,而不是直接输出 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 跟随重定向 // 添加 SSL 验证选项(开发环境可禁用,生产环境应启用) curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 禁用 SSL 证书验证 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 不检查证书中的主机名 // 3. 设置请求头 $headers = [ 'Accept: application/json', 'Authorization: Bearer ' . $this->userToken ]; curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // 4. 如果是 POST 请求,设置 POST 数据 if ($method === 'POST' && $data !== null) { curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); $headers[] = 'Content-Type: application/json'; curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); } // 5. 执行请求 $response = curl_exec($ch); // 6. 检查错误 if (curl_errno($ch)) { $error_msg = curl_error($ch); curl_close($ch); throw new Exception("cURL Error: " . $error_msg); } // 7. 获取 HTTP 状态码 $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); // 8. 处理响应 if ($httpCode >= 200 && $httpCode < 300) { // 成功响应 $decodedResponse = json_decode($response, true); if (json_last_error() === JSON_ERROR_NONE) { return $decodedResponse; } throw new Exception("JSON Decode Error: " . json_last_error_msg()); } else { // 错误响应 $errorResponse = json_decode($response, true); $errorMessage = $errorResponse['message'] ?? $response; throw new Exception("API Request Failed with HTTP Code {$httpCode}: {$errorMessage}"); } return null; } }旧PHP版SakuraFrpApi
张小明
前端开发工程师
老旧CentOS7服务器JVM加载Jar缓慢排查:竟与NTP服务器有关
老旧CentOS7服务器JVM加载Jar缓慢排查:竟与NTP服务器有关 近期维护一批老旧CentOS 7服务器时,遇到一个十分诡异的JVM故障——使用Java 8加载Jar包时速度异常缓慢,往往要等待数分钟甚至超时,而相同服务器切换到Java 17后࿰…
Tiez 贴汁 高效的剪贴工具
官方网站 https://tiez.name666.top/zh/ Tiez 贴汁 一贴即合,原汁原味。 不仅是高效的剪贴工具,更是您工作流中值得信赖的“铁汁”。
Git-RSCLIP企业级应用:国土调查外业核查前的自动化地物预判
Git-RSCLIP企业级应用:国土调查外业核查前的自动化地物预判 1. 为什么外业核查前需要“预判”? 你有没有遇到过这样的情况:一支国土调查队伍带着设备奔赴几十公里外的田间地头,结果发现——拍回来的照片里,本该是“设…
三天,用 AI 写了一个浏览器:真正强大的,还是程序员!
前段时间,Cursor宣布用AI写了一个浏览器FastRender,被全网嘲笑了。这个项目号称使用成百上千个并行 AI 智能体,连续跑了一周,生成了一个Web 浏览器,代码量超过 300 万行。但是很多程序员clone以后,却发现跑…
C++之【深入理解Vector】三部曲之二
前言:我们已经理解了vector的初始化和迭代器初始化,那么接下来要继续深入理解vector,它是如何扩容的,空间及数据个数是如何存储的。 vector空间增长问题 容量空间接口说明size获取数据个数capacity获取容量大小empty判断是否为空…
港科校友|李铭鸿,李泓曦:一脉相承
以信任和爱作为家庭的基石,校友李铭鸿Thomas和儿子李泓曦Conan先后踏上科大的教育之路,体现了大学一直培养的探索精神与独特个性。Conan全心投入本科学习,而父母灌输给他的自由、幸福和相互尊重的价值观继续引导着他,展示了科大一…