use anyhow::{Context, Result};
use serde_json::Value as JsonValue;
use crate::config::ContentTypeOverride;
#[derive(Debug, Clone, PartialEq)]
pub enum ContentType {
Json,
Xml,
Yaml,
}
impl ContentType {
pub fn from_header(header: Option<&str>) -> Self {
match header {
Some(h) => {
let lower = h.to_lowercase();
if lower.contains("application/json") || lower.contains("text/json") {
ContentType::Json
} else if lower.contains("application/xml") || lower.contains("text/xml") {
ContentType::Xml
} else if lower.contains("application/x-yaml")
|| lower.contains("text/yaml")
|| lower.contains("application/yaml")
{
ContentType::Yaml
} else {
ContentType::Json
}
}
None => ContentType::Json,
}
}
pub fn from_override(override_type: &ContentTypeOverride) -> Self {
match override_type {
ContentTypeOverride::Json => ContentType::Json,
ContentTypeOverride::Xml => ContentType::Xml,
ContentTypeOverride::Yaml => ContentType::Yaml,
}
}
}
pub fn parse_body(body: &str, content_type: &ContentType) -> Result<JsonValue> {
match content_type {
ContentType::Json => {
serde_json::from_str(body).context("Failed to parse response body as JSON")
}
ContentType::Xml => parse_xml(body),
ContentType::Yaml => {
serde_yaml::from_str(body).context("Failed to parse response body as YAML")
}
}
}
fn parse_xml(body: &str) -> Result<JsonValue> {
let value: JsonValue =
quick_xml::de::from_str(body).context("Failed to parse response body as XML")?;
Ok(value)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_content_type_detection() {
assert_eq!(
ContentType::from_header(Some("application/json")),
ContentType::Json
);
assert_eq!(
ContentType::from_header(Some("application/json; charset=utf-8")),
ContentType::Json
);
assert_eq!(
ContentType::from_header(Some("application/xml")),
ContentType::Xml
);
assert_eq!(
ContentType::from_header(Some("text/yaml")),
ContentType::Yaml
);
assert_eq!(ContentType::from_header(None), ContentType::Json);
assert_eq!(
ContentType::from_header(Some("text/plain")),
ContentType::Json
);
}
#[test]
fn test_parse_json() {
let body = r#"{"name": "test", "value": 42}"#;
let result = parse_body(body, &ContentType::Json).unwrap();
assert_eq!(result["name"], "test");
assert_eq!(result["value"], 42);
}
#[test]
fn test_parse_yaml() {
let body = "name: test\nvalue: 42\n";
let result = parse_body(body, &ContentType::Yaml).unwrap();
assert_eq!(result["name"], "test");
assert_eq!(result["value"], 42);
}
#[test]
fn test_parse_xml_simple() {
let body = "<root><name>test</name><value>42</value></root>";
let result = parse_body(body, &ContentType::Xml).unwrap();
assert!(result.get("name").is_some());
assert!(result.get("value").is_some());
}
#[test]
fn test_parse_xml_with_text_fields() {
let body = "<root><item><id>x1</id><name>Alice</name></item></root>";
let result = parse_body(body, &ContentType::Xml).unwrap();
let item = &result["item"];
assert!(item["id"].is_object() || item["id"].is_string());
}
}