rustack_sqs_http/
response.rs1use rustack_sqs_model::error::SqsError;
4
5use crate::body::SqsResponseBody;
6
7pub const CONTENT_TYPE: &str = "application/x-amz-json-1.0";
9
10#[must_use]
21pub fn error_to_json(error: &SqsError) -> Vec<u8> {
22 let obj = serde_json::json!({
23 "__type": error.code.error_type(),
24 "message": error.message,
25 });
26 serde_json::to_vec(&obj).expect("JSON serialization of error cannot fail")
27}
28
29#[must_use]
33pub fn error_to_response(error: &SqsError, request_id: &str) -> http::Response<SqsResponseBody> {
34 let json = error_to_json(error);
35 let crc = crc32fast::hash(&json);
36 let body = SqsResponseBody::from_json(json);
37
38 let mut response = http::Response::builder()
39 .status(error.code.status_code())
40 .header("content-type", CONTENT_TYPE)
41 .header("x-amzn-requestid", request_id)
42 .header("x-amzn-query-error", error.code.query_error_header())
43 .body(body)
44 .expect("valid error response");
45
46 if let Ok(hv) = http::HeaderValue::from_str(&crc.to_string()) {
47 response.headers_mut().insert("x-amz-crc32", hv);
48 }
49
50 response
51}
52
53#[must_use]
55pub fn json_response(json: Vec<u8>, request_id: &str) -> http::Response<SqsResponseBody> {
56 let crc = crc32fast::hash(&json);
57 let body = SqsResponseBody::from_json(json);
58
59 let mut response = http::Response::builder()
60 .status(http::StatusCode::OK)
61 .header("content-type", CONTENT_TYPE)
62 .header("x-amzn-requestid", request_id)
63 .body(body)
64 .expect("valid JSON response");
65
66 if let Ok(hv) = http::HeaderValue::from_str(&crc.to_string()) {
67 response.headers_mut().insert("x-amz-crc32", hv);
68 }
69
70 response
71}
72
73#[cfg(test)]
74mod tests {
75 use rustack_sqs_model::error::SqsErrorCode;
76
77 use super::*;
78
79 #[test]
80 fn test_should_format_error_json() {
81 let err = SqsError::new(
82 SqsErrorCode::NonExistentQueue,
83 "The specified queue does not exist.",
84 );
85 let json = error_to_json(&err);
86 let parsed: serde_json::Value = serde_json::from_slice(&json).unwrap();
87 assert_eq!(parsed["__type"], "AWS.SimpleQueueService.NonExistentQueue");
88 assert_eq!(parsed["message"], "The specified queue does not exist.");
89 }
90
91 #[test]
92 fn test_should_build_error_response_with_query_error_header() {
93 let err = SqsError::new(
94 SqsErrorCode::NonExistentQueue,
95 "The specified queue does not exist.",
96 );
97 let resp = error_to_response(&err, "test-req-123");
98 assert_eq!(resp.status(), http::StatusCode::BAD_REQUEST);
99 assert_eq!(resp.headers().get("content-type").unwrap(), CONTENT_TYPE);
100 assert_eq!(
101 resp.headers().get("x-amzn-query-error").unwrap(),
102 "AWS.SimpleQueueService.NonExistentQueue;Sender",
103 );
104 assert_eq!(
105 resp.headers().get("x-amzn-requestid").unwrap(),
106 "test-req-123",
107 );
108 assert!(resp.headers().get("x-amz-crc32").is_some());
109 }
110
111 #[test]
112 fn test_should_build_json_success_response() {
113 let json = serde_json::to_vec(
114 &serde_json::json!({"QueueUrl": "http://localhost:4566/000000000000/test"}),
115 )
116 .unwrap();
117 let resp = json_response(json, "req-456");
118 assert_eq!(resp.status(), http::StatusCode::OK);
119 assert_eq!(resp.headers().get("content-type").unwrap(), CONTENT_TYPE);
120 assert!(resp.headers().get("x-amz-crc32").is_some());
121 }
122}