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}