use axum::{
body::Body,
http::{response::Builder, HeaderName, HeaderValue},
response::{Html, IntoResponse, Response},
};
use axum_extra::extract::cookie::Cookie;
use bytes::{BufMut, BytesMut};
use hyper::{header, StatusCode};
use serde::Serialize;
use serde_json::json;
use super::views::ViewRenderer;
use crate::{controller::Json, Result};
pub fn empty() -> Result<Response> {
Ok(().into_response())
}
pub fn text(t: &str) -> Result<Response> {
Ok(t.to_string().into_response())
}
pub fn json<T: Serialize>(t: T) -> Result<Response> {
Ok(Json(t).into_response())
}
pub fn empty_json() -> Result<Response> {
json(json!({}))
}
pub fn html(content: &str) -> Result<Response> {
Ok(Html(content.to_string()).into_response())
}
pub fn view<V, S>(v: &V, key: &str, data: S) -> Result<Response>
where
V: ViewRenderer,
S: Serialize,
{
let res = v.render(key, data)?;
html(&res)
}
pub struct RenderBuilder {
response: Builder,
}
impl RenderBuilder {
#[must_use]
pub fn new() -> Self {
Self {
response: Builder::new().status(200),
}
}
#[must_use]
pub fn response(self) -> Builder {
self.response
}
#[must_use]
pub fn status<T>(self, status: T) -> Self
where
StatusCode: TryFrom<T>,
<StatusCode as TryFrom<T>>::Error: Into<axum::http::Error>,
{
Self {
response: self.response.status(status),
}
}
#[must_use]
pub fn header<K, V>(self, key: K, value: V) -> Self
where
HeaderName: TryFrom<K>,
<HeaderName as TryFrom<K>>::Error: Into<axum::http::Error>,
HeaderValue: TryFrom<V>,
<HeaderValue as TryFrom<V>>::Error: Into<axum::http::Error>,
{
Self {
response: self.response.header(key, value),
}
}
pub fn etag(self, etag: &str) -> Result<Self> {
Ok(Self {
response: self
.response
.header(header::ETAG, HeaderValue::from_str(etag)?),
})
}
pub fn cookies(self, cookies: &[Cookie<'_>]) -> Result<Self> {
let mut res = self.response;
for cookie in cookies {
let header_value = cookie.encoded().to_string().parse::<HeaderValue>()?;
res = res.header(header::SET_COOKIE, header_value);
}
Ok(Self { response: res })
}
pub fn text(self, content: &str) -> Result<Response> {
Ok(self
.response
.header(
header::CONTENT_TYPE,
HeaderValue::from_static(mime::TEXT_PLAIN_UTF_8.as_ref()),
)
.body(Body::from(content.to_string()))?)
}
pub fn empty(self) -> Result<Response> {
Ok(self.response.body(Body::empty())?)
}
pub fn view<V, S>(self, v: &V, key: &str, data: S) -> Result<Response>
where
V: ViewRenderer,
S: Serialize,
{
let content = v.render(key, data)?;
self.html(&content)
}
pub fn html(self, content: &str) -> Result<Response> {
Ok(self
.response
.header(
header::CONTENT_TYPE,
HeaderValue::from_static(mime::TEXT_HTML_UTF_8.as_ref()),
)
.body(Body::from(content.to_string()))?)
}
pub fn json<T>(self, item: T) -> Result<Response>
where
T: Serialize,
{
let mut buf = BytesMut::with_capacity(128).writer();
serde_json::to_writer(&mut buf, &item)?;
let body = Body::from(buf.into_inner().freeze());
Ok(self
.response
.header(
header::CONTENT_TYPE,
HeaderValue::from_static(mime::APPLICATION_JSON.as_ref()),
)
.body(body)?)
}
}
impl Default for RenderBuilder {
fn default() -> Self {
Self::new()
}
}
#[must_use]
pub fn render() -> RenderBuilder {
RenderBuilder::new()
}