use reqwest::header::HeaderMap;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type")]
pub enum XmlAuth {
None,
Bearer(String),
Basic { username: String, password: String },
#[serde(skip)]
Custom(HeaderMap),
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type")]
pub enum XmlPagination {
PageNumber {
param_name: String,
start_page: usize,
page_size: Option<usize>,
page_size_param: Option<String>,
},
Offset {
offset_param: String,
limit_param: String,
limit: usize,
},
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct XmlStreamConfig {
pub base_url: String,
pub path: String,
#[serde(with = "crate::serde_helpers::http_method")]
#[schemars(with = "String")]
pub method: reqwest::Method,
pub auth: XmlAuth,
#[serde(skip, default)]
pub headers: HeaderMap,
pub body: Option<String>,
pub records_element_path: Option<String>,
pub pagination: Option<XmlPagination>,
pub max_pages: Option<usize>,
pub query_params: std::collections::HashMap<String, String>,
}
impl XmlStreamConfig {
pub fn new(base_url: impl Into<String>, path: impl Into<String>) -> Self {
Self {
base_url: base_url.into(),
path: path.into(),
method: reqwest::Method::GET,
auth: XmlAuth::None,
headers: HeaderMap::new(),
body: None,
records_element_path: None,
pagination: None,
max_pages: None,
query_params: std::collections::HashMap::new(),
}
}
pub fn method(mut self, method: reqwest::Method) -> Self {
self.method = method;
self
}
pub fn auth(mut self, auth: XmlAuth) -> Self {
self.auth = auth;
self
}
pub fn headers(mut self, headers: HeaderMap) -> Self {
self.headers = headers;
self
}
pub fn body(mut self, body: impl Into<String>) -> Self {
self.body = Some(body.into());
self
}
pub fn records_element_path(mut self, path: impl Into<String>) -> Self {
self.records_element_path = Some(path.into());
self
}
pub fn pagination(mut self, pagination: XmlPagination) -> Self {
self.pagination = Some(pagination);
self
}
pub fn max_pages(mut self, max: usize) -> Self {
self.max_pages = Some(max);
self
}
pub fn query_param(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.query_params.insert(key.into(), value.into());
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_config() {
let config = XmlStreamConfig::new("https://api.example.com", "/users");
assert_eq!(config.base_url, "https://api.example.com");
assert_eq!(config.path, "/users");
assert_eq!(config.method, reqwest::Method::GET);
assert!(config.records_element_path.is_none());
}
#[test]
fn soap_config() {
let config = XmlStreamConfig::new("https://api.example.com", "/soap")
.method(reqwest::Method::POST)
.body("<Envelope><Body><GetUsers/></Body></Envelope>")
.records_element_path("Envelope.Body.GetUsersResponse.Users.User");
assert_eq!(config.method, reqwest::Method::POST);
assert!(config.body.is_some());
assert_eq!(
config.records_element_path.unwrap(),
"Envelope.Body.GetUsersResponse.Users.User"
);
}
}