borderless_runtime/
http.rs

1use bytes::Bytes;
2use http::request::Parts;
3use http::{header::CONTENT_TYPE, HeaderValue, StatusCode};
4use mime::{APPLICATION_JSON, TEXT_PLAIN_UTF_8};
5use serde::de::DeserializeOwned;
6use serde::Serialize;
7pub use tower::Service;
8
9#[cfg(feature = "contracts")]
10pub mod contract;
11
12#[cfg(feature = "agents")]
13pub mod agent;
14
15pub type Request<T = Bytes> = http::Request<T>;
16pub type Response<T = Bytes> = http::Response<T>;
17
18pub fn reject_404() -> Response {
19    let mut resp = Response::new(Bytes::new());
20    *resp.status_mut() = StatusCode::NOT_FOUND;
21    resp
22}
23
24pub fn method_not_allowed() -> Response {
25    let mut resp = Response::new(Bytes::new());
26    *resp.status_mut() = StatusCode::METHOD_NOT_ALLOWED;
27    resp
28}
29
30pub fn unsupported_media_type() -> Response {
31    let mut resp = Response::new(Bytes::new());
32    *resp.status_mut() = StatusCode::UNSUPPORTED_MEDIA_TYPE;
33    resp
34}
35
36pub fn bad_request(err: String) -> Response {
37    let mut resp = Response::new(err.into_bytes().into());
38    *resp.status_mut() = StatusCode::BAD_REQUEST;
39    resp
40}
41
42pub fn err_response(status: StatusCode, err_msg: String) -> Response {
43    let mut resp = Response::new(err_msg.into_bytes().into());
44    *resp.status_mut() = status;
45    resp
46}
47
48pub fn json_response<S: Serialize>(value: &S) -> Response<Bytes> {
49    let bytes = serde_json::to_vec(value).unwrap();
50    json_body(bytes)
51}
52
53pub fn json_body(bytes: Vec<u8>) -> Response<Bytes> {
54    let mut resp = Response::new(bytes.into());
55    resp.headers_mut().insert(
56        CONTENT_TYPE,
57        HeaderValue::from_static(APPLICATION_JSON.as_ref()),
58    );
59    resp
60}
61
62pub(crate) fn json_response_nested<S: Serialize + DeserializeOwned>(
63    value: S,
64    truncated_path: &str,
65) -> Response<Bytes> {
66    use borderless::__private::storage_traits::ToPayload;
67    match value.to_payload(truncated_path) {
68        Ok(Some(s)) => json_body(s.into_bytes()),
69        Ok(None) => json_response(&None::<()>),
70        Err(e) => into_server_error(e),
71    }
72}
73
74pub fn check_json_content(parts: &Parts) -> bool {
75    if let Some(content_type) = parts.headers.get(CONTENT_TYPE) {
76        content_type.as_bytes() == APPLICATION_JSON.as_ref().as_bytes()
77    } else {
78        false
79    }
80}
81
82/// Converts any error-type into a http-response with status-code 500
83///
84/// The response has content-type set to `text/plain; charset=utf-8`
85/// and the body contains the error message as string.
86pub fn into_server_error<E: ToString>(error: E) -> Response {
87    let mut resp = Response::new(error.to_string().into_bytes().into());
88    resp.headers_mut().append(
89        CONTENT_TYPE,
90        HeaderValue::from_static(TEXT_PLAIN_UTF_8.as_ref()),
91    );
92    *resp.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
93    resp
94}