dingtalk_stream/messages/
graph.rs1use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6pub struct GraphMessage;
8
9impl GraphMessage {
10 pub const TOPIC: &'static str = "/v1.0/graph/api/invoke";
12}
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct RequestLine {
17 #[serde(default = "default_method")]
19 pub method: String,
20 #[serde(default = "default_uri")]
22 pub uri: String,
23 #[serde(flatten)]
25 pub extensions: HashMap<String, serde_json::Value>,
26}
27
28impl Default for RequestLine {
29 fn default() -> Self {
30 Self {
31 method: "GET".to_owned(),
32 uri: "/".to_owned(),
33 extensions: HashMap::new(),
34 }
35 }
36}
37
38fn default_method() -> String {
39 "GET".to_owned()
40}
41
42fn default_uri() -> String {
43 "/".to_owned()
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct StatusLine {
49 #[serde(default = "default_status_code")]
51 pub code: u16,
52 #[serde(rename = "reasonPhrase", default = "default_reason")]
54 pub reason_phrase: String,
55 #[serde(flatten)]
57 pub extensions: HashMap<String, serde_json::Value>,
58}
59
60impl Default for StatusLine {
61 fn default() -> Self {
62 Self {
63 code: 200,
64 reason_phrase: "OK".to_owned(),
65 extensions: HashMap::new(),
66 }
67 }
68}
69
70fn default_status_code() -> u16 {
71 200
72}
73
74fn default_reason() -> String {
75 "OK".to_owned()
76}
77
78#[derive(Debug, Clone, Default, Serialize, Deserialize)]
80pub struct GraphRequest {
81 #[serde(skip_serializing_if = "Option::is_none")]
83 pub body: Option<String>,
84 #[serde(rename = "requestLine", default)]
86 pub request_line: RequestLine,
87 #[serde(default)]
89 pub headers: HashMap<String, String>,
90 #[serde(flatten)]
92 pub extensions: HashMap<String, serde_json::Value>,
93}
94
95#[derive(Debug, Clone, Default, Serialize, Deserialize)]
97pub struct GraphResponse {
98 #[serde(skip_serializing_if = "Option::is_none")]
100 pub body: Option<String>,
101 #[serde(default)]
103 pub headers: HashMap<String, String>,
104 #[serde(rename = "statusLine", default)]
106 pub status_line: StatusLine,
107 #[serde(flatten)]
109 pub extensions: HashMap<String, serde_json::Value>,
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115
116 #[test]
117 fn test_graph_request_deserialize() {
118 let json = r#"{
119 "body": "{\"key\":\"value\"}",
120 "requestLine": {"method": "POST", "uri": "/api/test"},
121 "headers": {"Content-Type": "application/json"}
122 }"#;
123 let req: GraphRequest = serde_json::from_str(json).unwrap();
124 assert_eq!(req.request_line.method, "POST");
125 assert_eq!(req.request_line.uri, "/api/test");
126 assert_eq!(req.headers.get("Content-Type").unwrap(), "application/json");
127 }
128
129 #[test]
130 fn test_graph_response_serialize() {
131 let resp = GraphResponse {
132 body: Some(r#"{"result":"ok"}"#.to_owned()),
133 headers: {
134 let mut h = HashMap::new();
135 h.insert("Content-Type".to_owned(), "application/json".to_owned());
136 h
137 },
138 status_line: StatusLine::default(),
139 extensions: HashMap::new(),
140 };
141 let json = serde_json::to_value(&resp).unwrap();
142 assert_eq!(json["statusLine"]["code"], 200);
143 assert_eq!(json["statusLine"]["reasonPhrase"], "OK");
144 }
145
146 #[test]
147 fn test_graph_message_topic() {
148 assert_eq!(GraphMessage::TOPIC, "/v1.0/graph/api/invoke");
149 }
150
151 #[test]
152 fn test_request_line_defaults() {
153 let rl = RequestLine::default();
154 assert_eq!(rl.method, "GET");
155 assert_eq!(rl.uri, "/");
156 }
157}