Skip to main content

gout_api/
admin.rs

1//! `GoutAdminClient` — 使用 admin key 管理 goutd。
2//!
3//! 负责 API key 的创建、列出和删除。
4//! 需要服务端启动时打印的 `admin-api-key`。
5
6use crate::{ApiResponse, CreateKeyRequest, CreateKeyResponse, KeyInfo};
7use anyhow::{Context, Result};
8
9/// 管理客户端。
10///
11/// 使用 `admin-api-key`(非普通隧道 key)进行认证。
12/// 用于创建/删除普通隧道 key。
13///
14/// # 示例
15///
16/// ```no_run
17/// # async fn doc() {
18/// use gout_api::admin::GoutAdminClient;
19///
20/// let admin = GoutAdminClient::new("server.example.com:8080", "admin-key");
21/// let key = admin.create_key("my laptop").await.unwrap();
22/// println!("new key: {}", key.key);
23/// # }
24/// ```
25pub struct GoutAdminClient {
26    inner: reqwest::Client,
27    base: String,
28    admin_key: String,
29}
30
31impl GoutAdminClient {
32    /// 创建一个新的 `GoutAdminClient`。
33    ///
34    /// # 参数
35    ///
36    /// * `server_addr` — 服务端地址,`host:port` 格式
37    /// * `admin_key` — 服务端首次启动时打印到 stdout 的 admin API key
38    pub fn new(server_addr: &str, admin_key: &str) -> Self {
39        Self {
40            inner: reqwest::Client::new(),
41            base: format!("http://{server_addr}"),
42            admin_key: admin_key.to_string(),
43        }
44    }
45
46    /// 创建一个普通 API key。
47    ///
48    /// 该 key 可用于 [`GoutClient`](crate::client::GoutClient) 进行隧道操作。
49    ///
50    /// # 参数
51    ///
52    /// * `name` — key 的备注名称(如 `"my laptop"`)
53    pub async fn create_key(&self, name: &str) -> Result<CreateKeyResponse> {
54        let resp = self
55            .inner
56            .post(format!("{}/api/v1/keys", self.base))
57            .header("X-Admin-Key", &self.admin_key)
58            .json(&CreateKeyRequest { name: name.into() })
59            .send()
60            .await
61            .context("REST create key failed")?;
62
63        crate::parse_api_response(resp).await
64    }
65
66    /// 列出所有普通 API key。
67    ///
68    /// 返回的列表中不包含 admin key。
69    pub async fn list_keys(&self) -> Result<Vec<KeyInfo>> {
70        let resp = self
71            .inner
72            .get(format!("{}/api/v1/keys", self.base))
73            .header("X-Admin-Key", &self.admin_key)
74            .send()
75            .await
76            .context("REST list keys failed")?;
77
78        crate::parse_api_response(resp).await
79    }
80
81    /// 删除一个 API key。
82    ///
83    /// 返回 `true` 表示删除成功,`false` 表示 key 不存在。
84    /// 不允许删除 admin key。
85    pub async fn delete_key(&self, key: &str) -> Result<bool> {
86        let resp = self
87            .inner
88            .delete(format!("{}/api/v1/keys/{}", self.base, key))
89            .header("X-Admin-Key", &self.admin_key)
90            .send()
91            .await
92            .context("REST delete key failed")?;
93
94        let j: ApiResponse<()> = resp.json().await?;
95        Ok(j.success)
96    }
97
98    /// 获取 admin key 值。
99    pub fn admin_key(&self) -> &str {
100        &self.admin_key
101    }
102}