drasi_bootstrap_http/
content_parser.rs1use anyhow::{Context, Result};
21use serde_json::Value as JsonValue;
22
23use crate::config::ContentTypeOverride;
24
25#[derive(Debug, Clone, PartialEq)]
27pub enum ContentType {
28 Json,
29 Xml,
30 Yaml,
31}
32
33impl ContentType {
34 pub fn from_header(header: Option<&str>) -> Self {
36 match header {
37 Some(h) => {
38 let lower = h.to_lowercase();
39 if lower.contains("application/json") || lower.contains("text/json") {
40 ContentType::Json
41 } else if lower.contains("application/xml") || lower.contains("text/xml") {
42 ContentType::Xml
43 } else if lower.contains("application/x-yaml")
44 || lower.contains("text/yaml")
45 || lower.contains("application/yaml")
46 {
47 ContentType::Yaml
48 } else {
49 ContentType::Json
51 }
52 }
53 None => ContentType::Json,
54 }
55 }
56
57 pub fn from_override(override_type: &ContentTypeOverride) -> Self {
59 match override_type {
60 ContentTypeOverride::Json => ContentType::Json,
61 ContentTypeOverride::Xml => ContentType::Xml,
62 ContentTypeOverride::Yaml => ContentType::Yaml,
63 }
64 }
65}
66
67pub fn parse_body(body: &str, content_type: &ContentType) -> Result<JsonValue> {
69 match content_type {
70 ContentType::Json => {
71 serde_json::from_str(body).context("Failed to parse response body as JSON")
72 }
73 ContentType::Xml => parse_xml(body),
74 ContentType::Yaml => {
75 serde_yaml::from_str(body).context("Failed to parse response body as YAML")
76 }
77 }
78}
79
80fn parse_xml(body: &str) -> Result<JsonValue> {
82 let value: JsonValue =
84 quick_xml::de::from_str(body).context("Failed to parse response body as XML")?;
85 Ok(value)
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn test_content_type_detection() {
94 assert_eq!(
95 ContentType::from_header(Some("application/json")),
96 ContentType::Json
97 );
98 assert_eq!(
99 ContentType::from_header(Some("application/json; charset=utf-8")),
100 ContentType::Json
101 );
102 assert_eq!(
103 ContentType::from_header(Some("application/xml")),
104 ContentType::Xml
105 );
106 assert_eq!(
107 ContentType::from_header(Some("text/yaml")),
108 ContentType::Yaml
109 );
110 assert_eq!(ContentType::from_header(None), ContentType::Json);
111 assert_eq!(
112 ContentType::from_header(Some("text/plain")),
113 ContentType::Json
114 );
115 }
116
117 #[test]
118 fn test_parse_json() {
119 let body = r#"{"name": "test", "value": 42}"#;
120 let result = parse_body(body, &ContentType::Json).unwrap();
121 assert_eq!(result["name"], "test");
122 assert_eq!(result["value"], 42);
123 }
124
125 #[test]
126 fn test_parse_yaml() {
127 let body = "name: test\nvalue: 42\n";
128 let result = parse_body(body, &ContentType::Yaml).unwrap();
129 assert_eq!(result["name"], "test");
130 assert_eq!(result["value"], 42);
131 }
132
133 #[test]
134 fn test_parse_xml_simple() {
135 let body = "<root><name>test</name><value>42</value></root>";
136 let result = parse_body(body, &ContentType::Xml).unwrap();
137 assert!(result.get("name").is_some());
138 assert!(result.get("value").is_some());
139 }
140
141 #[test]
142 fn test_parse_xml_with_text_fields() {
143 let body = "<root><item><id>x1</id><name>Alice</name></item></root>";
145 let result = parse_body(body, &ContentType::Xml).unwrap();
146 let item = &result["item"];
147 assert!(item["id"].is_object() || item["id"].is_string());
149 }
150}