awsim_core/protocol/
json.rs1use axum::http::{HeaderMap, StatusCode};
2use bytes::Bytes;
3use serde_json::Value;
4
5use crate::error::AwsError;
6
7use super::ParsedRequest;
8
9pub fn parse_request(headers: &HeaderMap, body: &Bytes) -> Result<ParsedRequest, AwsError> {
14 let target = headers
15 .get("x-amz-target")
16 .and_then(|v| v.to_str().ok())
17 .ok_or_else(|| AwsError::bad_request("MissingHeader", "Missing X-Amz-Target header"))?;
18
19 let operation = target
20 .split('.')
21 .last()
22 .ok_or_else(|| {
23 AwsError::bad_request(
24 "InvalidHeader",
25 format!("Invalid X-Amz-Target format: {target}"),
26 )
27 })?
28 .to_string();
29
30 let input = if body.is_empty() {
31 Value::Object(serde_json::Map::new())
32 } else {
33 serde_json::from_slice(body).map_err(|e| {
34 AwsError::bad_request("SerializationException", format!("Invalid JSON body: {e}"))
35 })?
36 };
37
38 Ok(ParsedRequest { operation, input })
39}
40
41pub fn serialize_response(
43 output: &Value,
44 request_id: &str,
45) -> (StatusCode, HeaderMap, Bytes) {
46 if let Some(raw_b64) = output.get("__raw_body").and_then(Value::as_str) {
47 use base64::Engine;
48 let data = base64::engine::general_purpose::STANDARD
49 .decode(raw_b64)
50 .unwrap_or_default();
51 let content_type = output
52 .get("__content_type")
53 .and_then(Value::as_str)
54 .unwrap_or("application/octet-stream");
55 let mut headers = HeaderMap::new();
56 headers.insert("content-type", content_type.parse().unwrap());
57 headers.insert("x-amzn-requestid", request_id.parse().unwrap());
58 return (StatusCode::OK, headers, Bytes::from(data));
59 }
60
61 let body = serde_json::to_vec(output).unwrap_or_default();
62 let mut headers = HeaderMap::new();
63 headers.insert("content-type", "application/x-amz-json-1.0".parse().unwrap());
64 headers.insert("x-amzn-requestid", request_id.parse().unwrap());
65 (StatusCode::OK, headers, Bytes::from(body))
66}
67
68pub fn serialize_error(
70 error: &AwsError,
71 request_id: &str,
72) -> (StatusCode, HeaderMap, Bytes) {
73 let body = serde_json::json!({
74 "__type": error.code,
75 "message": error.message,
76 });
77 let body = serde_json::to_vec(&body).unwrap_or_default();
78 let mut headers = HeaderMap::new();
79 headers.insert("content-type", "application/x-amz-json-1.0".parse().unwrap());
80 headers.insert("x-amzn-requestid", request_id.parse().unwrap());
81 headers.insert(
82 "x-amzn-errortype",
83 error.code.parse().unwrap(),
84 );
85 (error.status, headers, Bytes::from(body))
86}