use http::{Response, Version};
use crate::http_utils::IntoRawBytes;
pub type RawResponse = Response<Vec<u8>>;
pub trait IntoResponse {
fn response(self) -> RawResponse;
}
pub trait Action {
fn action(self) -> Option<RawResponse>;
}
impl<T> Action for T
where
T: IntoResponse,
{
fn action(self) -> Option<RawResponse> {
Some(self.response())
}
}
impl<T> Action for Response<T>
where
T: IntoRawBytes,
{
fn action(self) -> Option<RawResponse> {
Some(self.map(IntoRawBytes::into_raw_bytes))
}
}
impl Action for () {
fn action(self) -> Option<RawResponse> {
None
}
}
impl<T> Action for Option<T>
where
T: Action,
{
fn action(self) -> Option<RawResponse> {
self.and_then(Action::action)
}
}
impl<T, E> Action for Result<T, E>
where
T: Action,
E: Action,
{
fn action(self) -> Option<RawResponse> {
match self {
Ok(v) => v.action(),
Err(e) => e.action(),
}
}
}
impl IntoResponse for u16 {
fn response(self) -> RawResponse {
Response::builder()
.version(Version::HTTP_11)
.status(self)
.header("Content-Type", "text/plain; charset=UTF-8")
.header("Content-Length", "0")
.body(Vec::new())
.expect("Failed to build request")
}
}
pub struct Raw(Vec<u8>);
impl IntoResponse for Raw {
fn response(self) -> RawResponse {
Response::builder()
.version(Version::HTTP_11)
.status(200)
.header("Content-Type", "application/x-binary")
.header("Content-Length", format!("{}", self.0.len()))
.body(self.0)
.unwrap()
}
}
pub struct Plain(pub String);
impl IntoResponse for Plain {
fn response(self) -> RawResponse {
let bytes = self.0.into_bytes();
Response::builder()
.version(Version::HTTP_11)
.status(200)
.header("Content-Type", "text/plain; charset=utf-8")
.header("Content-Length", format!("{}", bytes.len()))
.body(bytes)
.unwrap()
}
}
pub struct Html(pub String);
impl IntoResponse for Html {
fn response(self) -> RawResponse {
let bytes = self.0.into_bytes();
Response::builder()
.version(Version::HTTP_11)
.status(200)
.header("Content-Type", "text/html; charset=utf-8")
.header("Content-Length", format!("{}", bytes.len()))
.body(bytes)
.unwrap()
}
}
pub struct Css(pub String);
impl IntoResponse for Css {
fn response(self) -> RawResponse {
let bytes = self.0.into_bytes();
Response::builder()
.version(Version::HTTP_11)
.status(200)
.header("Content-Type", "text/css; charset=utf-8")
.header("Content-Length", format!("{}", bytes.len()))
.body(bytes)
.unwrap()
}
}
pub struct Js(pub String);
impl IntoResponse for Js {
fn response(self) -> RawResponse {
let bytes = self.0.into_bytes();
Response::builder()
.version(Version::HTTP_11)
.status(200)
.header("Content-Type", "text/javascript; charset=utf-8")
.header("Content-Length", format!("{}", bytes.len()))
.body(bytes)
.unwrap()
}
}