rustack_logs_http/
response.rs1use rustack_logs_model::error::LogsError;
4
5use crate::body::LogsResponseBody;
6
7pub const CONTENT_TYPE: &str = "application/x-amz-json-1.1";
9
10#[must_use]
23pub fn error_to_json(error: &LogsError) -> Vec<u8> {
24 let obj = serde_json::json!({
25 "__type": error.error_type(),
26 "message": error.message,
27 });
28 serde_json::to_vec(&obj).expect("JSON serialization of error cannot fail")
29}
30
31#[must_use]
33pub fn error_to_response(error: &LogsError, request_id: &str) -> http::Response<LogsResponseBody> {
34 let json = error_to_json(error);
35 let crc = crc32fast::hash(&json);
36 let body = LogsResponseBody::from_json(json);
37
38 let mut response = http::Response::builder()
39 .status(error.status_code)
40 .header("content-type", CONTENT_TYPE)
41 .header("x-amzn-requestid", request_id)
42 .body(body)
43 .expect("valid error response");
44
45 if let Ok(hv) = http::HeaderValue::from_str(&crc.to_string()) {
46 response.headers_mut().insert("x-amz-crc32", hv);
47 }
48
49 response
50}
51
52#[must_use]
54pub fn json_response(json: Vec<u8>, request_id: &str) -> http::Response<LogsResponseBody> {
55 let crc = crc32fast::hash(&json);
56 let body = LogsResponseBody::from_json(json);
57
58 let mut response = http::Response::builder()
59 .status(http::StatusCode::OK)
60 .header("content-type", CONTENT_TYPE)
61 .header("x-amzn-requestid", request_id)
62 .body(body)
63 .expect("valid JSON response");
64
65 if let Ok(hv) = http::HeaderValue::from_str(&crc.to_string()) {
66 response.headers_mut().insert("x-amz-crc32", hv);
67 }
68
69 response
70}
71
72#[cfg(test)]
73mod tests {
74 use rustack_logs_model::error::LogsErrorCode;
75
76 use super::*;
77
78 #[test]
79 fn test_should_format_error_json_with_short_type() {
80 let err = LogsError::with_message(
81 LogsErrorCode::ResourceNotFoundException,
82 "Log group my-group not found",
83 );
84 let json = error_to_json(&err);
85 let parsed: serde_json::Value = serde_json::from_slice(&json).expect("valid JSON");
86 assert_eq!(parsed["__type"], "ResourceNotFoundException");
87 assert_eq!(parsed["message"], "Log group my-group not found");
88 }
89
90 #[test]
91 fn test_should_build_error_response_with_correct_status() {
92 let err = LogsError::with_message(LogsErrorCode::ResourceNotFoundException, "not found");
93 let resp = error_to_response(&err, "test-req-123");
94 assert_eq!(resp.status(), http::StatusCode::BAD_REQUEST);
95 assert_eq!(
96 resp.headers()
97 .get("content-type")
98 .expect("has content-type"),
99 CONTENT_TYPE,
100 );
101 assert_eq!(
102 resp.headers()
103 .get("x-amzn-requestid")
104 .expect("has request id"),
105 "test-req-123",
106 );
107 assert!(resp.headers().get("x-amz-crc32").is_some());
108 }
109
110 #[test]
111 fn test_should_build_json_success_response() {
112 let json = serde_json::to_vec(&serde_json::json!({"logGroupName": "/aws/test"}))
113 .expect("valid JSON");
114 let resp = json_response(json, "req-456");
115 assert_eq!(resp.status(), http::StatusCode::OK);
116 assert_eq!(
117 resp.headers()
118 .get("content-type")
119 .expect("has content-type"),
120 CONTENT_TYPE,
121 );
122 assert!(resp.headers().get("x-amz-crc32").is_some());
123 }
124
125 #[test]
126 fn test_should_use_1_1_content_type() {
127 assert_eq!(CONTENT_TYPE, "application/x-amz-json-1.1");
128 }
129}