use serde::Serialize;
pub enum ResponseBody {
Text(String),
Bytes(Vec<u8>),
}
impl Default for ResponseBody {
fn default() -> Self { ResponseBody::Text(String::new()) }
}
impl From<&str> for ResponseBody {
fn from(s: &str) -> Self { ResponseBody::Text(s.to_string()) }
}
impl From<String> for ResponseBody {
fn from(s: String) -> Self { ResponseBody::Text(s) }
}
#[derive(Default)]
pub struct Response {
pub status: u16,
pub headers: Vec<(String, String)>,
pub body: ResponseBody,
}
impl Response {
pub fn ok(body: impl Into<String>) -> Self {
Self {
status: 200,
body: ResponseBody::Text(body.into()),
headers: vec![],
}
}
pub fn with_header(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.headers.push((key.into(), value.into()));
self
}
pub fn binary(status: u16, bytes: Vec<u8>, content_type: &str) -> Self {
Self {
status,
body: ResponseBody::Bytes(bytes),
headers: vec![("content-type".into(), content_type.into())],
}
}
}
pub trait IntoResponse {
fn into_response(self) -> Response;
}
impl IntoResponse for Response {
fn into_response(self) -> Response { self }
}
impl IntoResponse for &'static str {
fn into_response(self) -> Response { Response::ok(self) }
}
impl IntoResponse for String {
fn into_response(self) -> Response { Response::ok(self) }
}
pub struct Json<T>(pub T);
impl<T: Serialize> IntoResponse for Json<T> {
fn into_response(self) -> Response {
match serde_json::to_string(&self.0) {
Ok(body) => Response::ok(body),
Err(e) => Response {
status: 500,
body: ResponseBody::Text(e.to_string()),
headers: vec![],
},
}
}
}
impl<T: IntoResponse> IntoResponse for crate::error::Result<T> {
fn into_response(self) -> Response {
match self {
Ok(v) => v.into_response(),
Err(e) => e.into_response(),
}
}
}