bangumi_api/common/
model.rs

1use anyhow::{Result, bail};
2
3use super::error::BangumiError;
4
5/// 用于与Bangumi API进行交互的客户端
6///
7/// 提供了构建请求、发送请求以及处理响应的功能
8pub struct BangumiClient {
9    /// API的基础路径
10    pub base_path: String,
11    /// 可选的User-Agent头,用于标识请求来源
12    pub user_agent: Option<String>,
13    /// reqwest HTTP客户端,用于发送实际的网络请求
14    pub client: reqwest::Client,
15    /// 可选的访问令牌,用于认证需要授权的API请求
16    pub access_token: Option<String>,
17}
18
19/// 为BangumiClient提供默认实现
20///
21/// 默认配置:
22/// - 使用"https://api.bgm.tv"作为基础路径
23/// - 设置特定格式的User-Agent
24/// - 初始化一个基本的reqwest客户端
25/// - 不包含访问令牌
26impl Default for BangumiClient {
27    fn default() -> Self {
28        BangumiClient {
29            base_path: "https://api.bgm.tv".to_string(),
30            user_agent: Some(
31                "waitsalt/bangumi-api (https://github.com/waitsalt/bangumi-api)".to_string(),
32            ),
33            client: reqwest::Client::new(),
34            access_token: None,
35        }
36    }
37}
38
39impl BangumiClient {
40    /// 创建一个新的BangumiClient实例
41    ///
42    /// # 参数
43    /// - `base_path`: API的基础路径
44    /// - `user_agent`: 可选的User-Agent头
45    /// - `access_token`: 可选的访问令牌
46    ///
47    /// # 返回
48    /// 返回一个使用指定参数配置的BangumiClient实例
49    pub fn new(
50        base_path: String,
51        user_agent: Option<String>,
52        access_token: Option<String>,
53    ) -> Self {
54        BangumiClient {
55            base_path,
56            user_agent,
57            client: reqwest::Client::new(),
58            access_token,
59        }
60    }
61
62    /// 构建HTTP请求
63    ///
64    /// 根据提供的HTTP方法和URL创建一个RequestBuilder实例,并设置必要的请求头
65    ///
66    /// # 参数
67    /// - `method`: HTTP请求方法
68    /// - `url`: 请求的URL
69    ///
70    /// # 返回
71    /// 返回一个配置了User-Agent和Bearer Token(如果有)的RequestBuilder
72    pub fn request_builder(&self, method: reqwest::Method, url: &str) -> reqwest::RequestBuilder {
73        let mut builder = self.client.request(method, url);
74
75        // 设置User-Agent头(如果有)
76        if let Some(ua) = &self.user_agent {
77            builder = builder.header(reqwest::header::USER_AGENT, ua);
78        }
79
80        // 设置Bearer Token(如果有)
81        if let Some(token) = &self.access_token {
82            builder = builder.bearer_auth(token);
83        }
84
85        builder
86    }
87
88    /// 发送HTTP请求并处理响应
89    ///
90    /// 执行RequestBuilder构建的请求,并根据响应状态码进行相应处理
91    ///
92    /// # 参数
93    /// - `request_builder`: 包含请求信息的RequestBuilder
94    ///
95    /// # 返回
96    /// - 如果请求成功(状态码200-299),返回包含响应的Result
97    /// - 如果请求失败,将响应体解析为BangumiError并返回错误
98    pub async fn request_send(
99        &self,
100        request_builder: reqwest::RequestBuilder,
101    ) -> Result<reqwest::Response> {
102        // 发送请求并获取响应
103        let response = request_builder.send().await?;
104        // 获取响应状态码
105        let status_code = response.status();
106        // 判断请求是否成功
107        match status_code.is_success() {
108            true => {
109                // 请求成功,返回响应
110                return Ok(response);
111            }
112            false => {
113                // 请求失败,将响应体解析为错误信息
114                let res: BangumiError = response.json().await?;
115                bail!(format!("请求错误: {:?}", res))
116            }
117        }
118    }
119}