open_lark/core/request_builder/
mod.rs

1mod auth_handler;
2mod header_builder;
3mod multipart_builder;
4
5pub use auth_handler::AuthHandler;
6pub use header_builder::HeaderBuilder;
7pub use multipart_builder::MultipartBuilder;
8
9use crate::core::{
10    api_req::ApiRequest, config::Config, constants::AccessTokenType, error::LarkAPIError,
11    req_option::RequestOption,
12};
13use reqwest::RequestBuilder;
14use std::{future::Future, pin::Pin};
15
16/// 统一的请求构建器,负责协调各个子构建器
17pub struct UnifiedRequestBuilder;
18
19impl UnifiedRequestBuilder {
20    pub fn build<'a>(
21        req: &'a mut ApiRequest,
22        access_token_type: AccessTokenType,
23        config: &'a Config,
24        option: &'a RequestOption,
25    ) -> Pin<Box<dyn Future<Output = Result<RequestBuilder, LarkAPIError>> + Send + 'a>> {
26        Box::pin(async move {
27            // 1. 构建基础请求
28            let url = Self::build_url(config, req)?;
29            let mut req_builder = config
30                .http_client
31                .request(req.http_method.clone(), url.as_ref());
32
33            // 2. 构建请求头
34            req_builder = HeaderBuilder::build_headers(req_builder, config, option);
35
36            // 3. 处理认证
37            req_builder =
38                AuthHandler::apply_auth(req_builder, access_token_type, config, option).await?;
39
40            // 4. 处理请求体
41            if !req.file.is_empty() {
42                req_builder = MultipartBuilder::build_multipart(req_builder, &req.body, &req.file)?;
43            } else if !req.body.is_empty() {
44                req_builder = req_builder.body(req.body.clone());
45                req_builder = req_builder.header(
46                    crate::core::constants::CONTENT_TYPE_HEADER,
47                    crate::core::constants::DEFAULT_CONTENT_TYPE,
48                );
49            }
50
51            Ok(req_builder)
52        })
53    }
54
55    fn build_url(config: &Config, req: &ApiRequest) -> Result<url::Url, LarkAPIError> {
56        let path = format!("{}{}", config.base_url, req.api_path);
57        let query_params = req
58            .query_params
59            .iter()
60            .map(|(k, v)| (k.as_str(), v.as_str()))
61            .collect::<Vec<_>>();
62        Ok(url::Url::parse_with_params(&path, query_params)?)
63    }
64}