#![allow(dead_code)]
use crate::{
config::Config,
constants::{CUSTOM_REQUEST_ID, USER_AGENT_HEADER},
req_option::RequestOption,
utils::user_agent,
};
use reqwest::RequestBuilder;
pub struct HeaderBuilder;
impl HeaderBuilder {
pub fn build_headers(
mut req_builder: RequestBuilder,
config: &Config,
option: &RequestOption,
) -> RequestBuilder {
if let Some(ref request_id) = option.request_id {
req_builder = req_builder.header(CUSTOM_REQUEST_ID, request_id);
}
for (key, value) in &option.header {
req_builder = req_builder.header(key, value);
}
for (key, value) in config.header() {
req_builder = req_builder.header(key, value);
}
req_builder = req_builder.header(USER_AGENT_HEADER, user_agent());
req_builder
}
pub fn add_header(req_builder: RequestBuilder, key: &str, value: &str) -> RequestBuilder {
req_builder.header(key, value)
}
pub fn add_headers(
mut req_builder: RequestBuilder,
headers: &[(String, String)],
) -> RequestBuilder {
for (key, value) in headers {
req_builder = req_builder.header(key, value);
}
req_builder
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::constants::AppType;
use reqwest::Client;
use std::collections::HashMap;
fn create_test_config() -> Config {
let mut headers = HashMap::new();
headers.insert("X-Global-Header".to_string(), "global-value".to_string());
headers.insert("X-App-Version".to_string(), "1.0.0".to_string());
Config::builder()
.app_id("test_app_id")
.app_secret("test_app_secret")
.app_type(AppType::SelfBuild)
.header(headers)
.build()
}
fn create_test_request_option() -> RequestOption {
let mut option = RequestOption {
request_id: Some("test-request-123".to_string()),
..Default::default()
};
option
.header
.insert("X-Custom-Header".to_string(), "custom-value".to_string());
option
.header
.insert("X-Test-Flag".to_string(), "true".to_string());
option
}
fn create_test_request_builder() -> RequestBuilder {
Client::new().get("https://test.api.example.com/test")
}
#[test]
fn test_header_builder_struct_creation() {
let _builder = HeaderBuilder;
}
#[test]
fn test_build_headers_with_all_options() {
let req_builder = create_test_request_builder();
let config = create_test_config();
let option = create_test_request_option();
let result = HeaderBuilder::build_headers(req_builder, &config, &option);
assert!(format!("{:?}", result).contains("RequestBuilder"));
}
#[test]
fn test_build_headers_with_empty_request_id() {
let req_builder = create_test_request_builder();
let config = create_test_config();
let mut option = create_test_request_option();
option.request_id = None;
let result = HeaderBuilder::build_headers(req_builder, &config, &option);
assert!(format!("{:?}", result).contains("RequestBuilder"));
}
#[test]
fn test_build_headers_with_empty_headers() {
let req_builder = create_test_request_builder();
let config = Config::builder()
.app_id("test_app_id")
.app_secret("test_app_secret")
.app_type(AppType::SelfBuild)
.header(HashMap::new()) .build();
let mut option = create_test_request_option();
option.header.clear();
let result = HeaderBuilder::build_headers(req_builder, &config, &option);
assert!(format!("{:?}", result).contains("RequestBuilder"));
}
#[test]
fn test_build_headers_user_agent_always_added() {
let req_builder = create_test_request_builder();
let config = Config::default(); let option = RequestOption::default();
let result = HeaderBuilder::build_headers(req_builder, &config, &option);
assert!(format!("{:?}", result).contains("RequestBuilder"));
}
#[test]
fn test_build_headers_header_precedence() {
let req_builder = create_test_request_builder();
let mut config_headers = HashMap::new();
config_headers.insert("X-Global-Header".to_string(), "global-value".to_string());
config_headers.insert("X-App-Version".to_string(), "1.0.0".to_string());
config_headers.insert("X-Common-Header".to_string(), "config-value".to_string());
let config = Config::builder()
.app_id("test_app_id")
.app_secret("test_app_secret")
.app_type(AppType::SelfBuild)
.header(config_headers)
.build();
let mut option = create_test_request_option();
option
.header
.insert("X-Common-Header".to_string(), "option-value".to_string());
let result = HeaderBuilder::build_headers(req_builder, &config, &option);
assert!(format!("{:?}", result).contains("RequestBuilder"));
}
#[test]
fn test_add_header() {
let req_builder = create_test_request_builder();
let key = "X-Test-Header";
let value = "test-value";
let result = HeaderBuilder::add_header(req_builder, key, value);
assert!(format!("{:?}", result).contains("RequestBuilder"));
}
#[test]
fn test_add_header_with_empty_values() {
let req_builder = create_test_request_builder();
let result = HeaderBuilder::add_header(req_builder, "", "");
assert!(format!("{:?}", result).contains("RequestBuilder"));
}
#[test]
fn test_add_headers_empty_list() {
let req_builder = create_test_request_builder();
let headers: &[(String, String)] = &[];
let result = HeaderBuilder::add_headers(req_builder, headers);
assert!(format!("{:?}", result).contains("RequestBuilder"));
}
#[test]
fn test_add_headers_multiple() {
let req_builder = create_test_request_builder();
let headers = &[
("X-Header-1".to_string(), "value-1".to_string()),
("X-Header-2".to_string(), "value-2".to_string()),
("X-Header-3".to_string(), "value-3".to_string()),
];
let result = HeaderBuilder::add_headers(req_builder, headers);
assert!(format!("{:?}", result).contains("RequestBuilder"));
}
#[test]
fn test_add_headers_duplicate_keys() {
let req_builder = create_test_request_builder();
let headers = &[
("X-Duplicate".to_string(), "value-1".to_string()),
("X-Duplicate".to_string(), "value-2".to_string()),
("X-Other".to_string(), "other-value".to_string()),
];
let result = HeaderBuilder::add_headers(req_builder, headers);
assert!(format!("{:?}", result).contains("RequestBuilder"));
}
#[test]
fn test_header_builder_is_send_sync() {
fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}
assert_send::<HeaderBuilder>();
assert_sync::<HeaderBuilder>();
}
#[test]
fn test_build_headers_with_large_number_of_headers() {
let req_builder = create_test_request_builder();
let mut config_headers = HashMap::new();
config_headers.insert("X-Global-Header".to_string(), "global-value".to_string());
config_headers.insert("X-App-Version".to_string(), "1.0.0".to_string());
for i in 0..50 {
config_headers.insert(format!("X-Config-Header-{i}"), format!("config-value-{i}"));
}
let config = Config::builder()
.app_id("test_app_id")
.app_secret("test_app_secret")
.app_type(AppType::SelfBuild)
.header(config_headers)
.build();
let mut option = create_test_request_option();
for i in 0..50 {
option
.header
.insert(format!("X-Option-Header-{i}"), format!("option-value-{i}"));
}
let result = HeaderBuilder::build_headers(req_builder, &config, &option);
assert!(format!("{:?}", result).contains("RequestBuilder"));
}
#[test]
fn test_build_headers_with_special_characters() {
let req_builder = create_test_request_builder();
let mut config_headers = HashMap::new();
config_headers.insert("X-Global-Header".to_string(), "global-value".to_string());
config_headers.insert("X-App-Version".to_string(), "1.0.0".to_string());
config_headers.insert("X-Unicode".to_string(), "测试中文".to_string());
let config = Config::builder()
.app_id("test_app_id")
.app_secret("test_app_secret")
.app_type(AppType::SelfBuild)
.header(config_headers)
.build();
let mut option = create_test_request_option();
option.header.insert(
"X-Special-Chars".to_string(),
"value with spaces & symbols!".to_string(),
);
let result = HeaderBuilder::build_headers(req_builder, &config, &option);
assert!(format!("{:?}", result).contains("RequestBuilder"));
}
#[test]
fn test_build_headers_preserves_request_builder_type() {
let req_builder = create_test_request_builder();
let config = create_test_config();
let option = create_test_request_option();
let result = HeaderBuilder::build_headers(req_builder, &config, &option);
let final_result = result.header("Additional-Header", "additional-value");
assert!(format!("{:?}", final_result).contains("RequestBuilder"));
}
}