Skip to main content

aep_tower/
response.rs

1use aep_core::{ErrorCode, new_problem_details};
2use aep_service::ServiceResponse;
3use bytes::Bytes;
4use http::{HeaderValue, Response, StatusCode, header};
5use http_body_util::Full;
6
7use crate::TowerError;
8
9pub type HttpResponse = Response<Full<Bytes>>;
10
11pub(crate) fn service_response(response: ServiceResponse) -> Result<HttpResponse, TowerError> {
12    let status = StatusCode::from_u16(response.status).map_err(|_| {
13        TowerError::InvalidConfiguration("Service returned an invalid HTTP status".to_owned())
14    })?;
15    let body = serde_json::to_vec(&response.to_json()?)?;
16    let mut result = Response::new(Full::new(Bytes::from(body)));
17    *result.status_mut() = status;
18    *result.headers_mut() = response.headers;
19    Ok(result)
20}
21
22pub(crate) fn json_response(
23    status: StatusCode,
24    content_type: &'static str,
25    value: &impl serde::Serialize,
26) -> Result<HttpResponse, TowerError> {
27    let mut response = Response::new(Full::new(Bytes::from(serde_json::to_vec(value)?)));
28    *response.status_mut() = status;
29    response
30        .headers_mut()
31        .insert(header::CONTENT_TYPE, HeaderValue::from_static(content_type));
32    Ok(response)
33}
34
35pub(crate) fn problem_response(code: ErrorCode, status: StatusCode) -> HttpResponse {
36    let title = code
37        .as_str()
38        .split('_')
39        .map(|part| {
40            let mut characters = part.chars();
41            characters.next().map_or_else(String::new, |first| {
42                first.to_uppercase().collect::<String>() + characters.as_str()
43            })
44        })
45        .collect::<Vec<_>>()
46        .join(" ");
47    let problem = new_problem_details(code, title, i64::from(status.as_u16()));
48    json_response(status, aep_core::PROBLEM_MEDIA_TYPE, &problem)
49        .unwrap_or_else(|_| empty_response(StatusCode::INTERNAL_SERVER_ERROR))
50}
51
52pub(crate) fn method_not_allowed(method: &'static str) -> HttpResponse {
53    let mut response = empty_response(StatusCode::METHOD_NOT_ALLOWED);
54    response
55        .headers_mut()
56        .insert(header::ALLOW, HeaderValue::from_static(method));
57    response
58}
59
60pub(crate) fn empty_response(status: StatusCode) -> HttpResponse {
61    let mut response = Response::new(Full::new(Bytes::new()));
62    *response.status_mut() = status;
63    response
64}
65
66pub(crate) fn internal_error() -> HttpResponse {
67    empty_response(StatusCode::INTERNAL_SERVER_ERROR)
68}