Skip to main content

rustack_cloudfront_http/
response.rs

1//! HTTP response helpers.
2
3use http::{HeaderValue, Response, StatusCode};
4use rustack_cloudfront_model::CloudFrontError;
5
6use crate::{service::HttpBody, xml::ser::error_xml};
7
8/// Turn a `CloudFrontError` into an HTTP response.
9pub fn error_response(err: &CloudFrontError, request_id: &str) -> Response<HttpBody> {
10    let status =
11        StatusCode::from_u16(err.http_status()).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR);
12    let xml = error_xml(err.code(), &err.message(), request_id);
13    let mut resp = Response::builder()
14        .status(status)
15        .header(http::header::CONTENT_TYPE, "text/xml")
16        .body(HttpBody::from(xml))
17        .unwrap_or_else(|_| Response::new(HttpBody::from(String::new())));
18    if let Ok(hv) = HeaderValue::from_str(err.code()) {
19        resp.headers_mut().insert("x-amzn-errortype", hv);
20    }
21    if let Ok(hv) = HeaderValue::from_str(request_id) {
22        resp.headers_mut().insert("x-amzn-requestid", hv);
23    }
24    resp
25}
26
27/// Build an XML response with `ETag`, `Content-Type`, and optional `Location` headers.
28pub fn xml_response(status: StatusCode, body: String, etag: Option<&str>) -> Response<HttpBody> {
29    let mut builder = Response::builder()
30        .status(status)
31        .header(http::header::CONTENT_TYPE, "application/xml");
32    if let Some(tag) = etag {
33        builder = builder.header(http::header::ETAG, tag);
34    }
35    builder
36        .body(HttpBody::from(body))
37        .unwrap_or_else(|_| Response::new(HttpBody::from(String::new())))
38}
39
40/// Empty 204 response.
41pub fn empty_204() -> Response<HttpBody> {
42    Response::builder()
43        .status(StatusCode::NO_CONTENT)
44        .body(HttpBody::default())
45        .unwrap_or_else(|_| Response::new(HttpBody::default()))
46}