rustack_cloudfront_http/
response.rs1use bytes::Bytes;
4use http::{HeaderValue, Response, StatusCode};
5use rustack_cloudfront_model::CloudFrontError;
6
7use crate::{service::HttpBody, xml::ser::error_xml};
8
9pub fn error_response(err: &CloudFrontError, request_id: &str) -> Response<HttpBody> {
11 let status =
12 StatusCode::from_u16(err.http_status()).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR);
13 let xml = error_xml(err.code(), &err.message(), request_id);
14 let mut resp = Response::builder()
15 .status(status)
16 .header(http::header::CONTENT_TYPE, "text/xml")
17 .body(HttpBody::from(xml))
18 .unwrap_or_else(|_| Response::new(HttpBody::from(String::new())));
19 if let Ok(hv) = HeaderValue::from_str(err.code()) {
20 resp.headers_mut().insert("x-amzn-errortype", hv);
21 }
22 if let Ok(hv) = HeaderValue::from_str(request_id) {
23 resp.headers_mut().insert("x-amzn-requestid", hv);
24 }
25 resp
26}
27
28pub fn xml_response(status: StatusCode, body: String, etag: Option<&str>) -> Response<HttpBody> {
30 let mut builder = Response::builder()
31 .status(status)
32 .header(http::header::CONTENT_TYPE, "application/xml");
33 if let Some(tag) = etag {
34 builder = builder.header(http::header::ETAG, tag);
35 }
36 builder
37 .body(HttpBody::from(body))
38 .unwrap_or_else(|_| Response::new(HttpBody::from(String::new())))
39}
40
41pub fn bytes_response(
43 status: StatusCode,
44 body: Bytes,
45 content_type: &'static str,
46 etag: Option<&str>,
47) -> Response<HttpBody> {
48 let mut builder = Response::builder()
49 .status(status)
50 .header(http::header::CONTENT_TYPE, content_type);
51 if let Some(tag) = etag {
52 builder = builder.header(http::header::ETAG, tag);
53 }
54 builder
55 .body(HttpBody::from(body))
56 .unwrap_or_else(|_| Response::new(HttpBody::default()))
57}
58
59pub fn empty_204() -> Response<HttpBody> {
61 Response::builder()
62 .status(StatusCode::NO_CONTENT)
63 .body(HttpBody::default())
64 .unwrap_or_else(|_| Response::new(HttpBody::default()))
65}
66
67#[cfg(test)]
68mod tests {
69 use bytes::Bytes;
70 use http_body_util::BodyExt;
71
72 use super::*;
73
74 #[tokio::test]
75 async fn test_should_build_bytes_response_with_etag() {
76 let response = bytes_response(
77 StatusCode::OK,
78 Bytes::from_static(b"function code"),
79 "application/octet-stream",
80 Some("etag-1"),
81 );
82
83 assert_eq!(response.status(), StatusCode::OK);
84 assert_eq!(
85 response.headers().get(http::header::CONTENT_TYPE),
86 Some(&HeaderValue::from_static("application/octet-stream")),
87 );
88 assert_eq!(
89 response.headers().get(http::header::ETAG),
90 Some(&HeaderValue::from_static("etag-1")),
91 );
92 let body = response.into_body().collect().await.unwrap().to_bytes();
93 assert_eq!(body, Bytes::from_static(b"function code"));
94 }
95}