omnia_sdk/api/
into_http.rs1use axum::response::{IntoResponse, Response};
2use http::header::CONTENT_TYPE;
3use http::{HeaderValue, StatusCode};
4
5use crate::api::Body;
6use crate::api::reply::Reply;
7
8#[allow(type_alias_bounds)]
10pub type HttpResult<T: IntoResponse, E: IntoResponse = HttpError> = Result<T, E>;
11
12pub trait IntoBody: Body {
15 fn into_body(self) -> anyhow::Result<Vec<u8>>;
22}
23
24impl<T> IntoResponse for Reply<T>
25where
26 T: IntoBody,
27{
28 fn into_response(self) -> Response {
29 let body = match self.body.into_body() {
30 Ok(v) => v,
31 Err(e) => {
32 return (StatusCode::INTERNAL_SERVER_ERROR, format!("body encoding error: {e}"))
33 .into_response();
34 }
35 };
36
37 let mut hm = self.headers;
38 if !hm.contains_key(CONTENT_TYPE) {
39 hm.insert(CONTENT_TYPE, HeaderValue::from_static("text/plain; charset=utf-8"));
40 }
41
42 let status = self.status;
43 (status, hm, body).into_response()
44 }
45}
46
47pub struct HttpError {
49 status: StatusCode,
50 error: String,
51}
52
53impl From<crate::Error> for HttpError {
54 fn from(e: crate::Error) -> Self {
55 Self {
56 status: e.status(),
57 error: e.to_string(),
58 }
59 }
60}
61
62impl From<anyhow::Error> for HttpError {
63 fn from(e: anyhow::Error) -> Self {
64 let error = format!("{e}, caused by: {}", e.root_cause());
65 let status =
66 e.downcast_ref().map_or(StatusCode::INTERNAL_SERVER_ERROR, crate::Error::status);
67 Self { status, error }
68 }
69}
70
71impl IntoResponse for HttpError {
72 fn into_response(self) -> axum::response::Response {
73 (self.status, self.error).into_response()
74 }
75}