soph_server/response/
builder.rsuse crate::ServerResult;
use axum::{
body::Body,
http::{header, response::Builder, HeaderName, HeaderValue, StatusCode},
response::Response,
};
use std::any::Any;
pub struct ResponseBuilder {
inner: Builder,
}
impl Default for ResponseBuilder {
fn default() -> Self {
Self::new()
}
}
impl ResponseBuilder {
fn new() -> Self {
Self {
inner: Builder::new().status(StatusCode::OK),
}
}
pub fn builder(self) -> Builder {
self.inner
}
pub fn status<T>(self, status: T) -> Self
where
StatusCode: TryFrom<T>,
<StatusCode as TryFrom<T>>::Error: Into<axum::http::Error>,
{
Self {
inner: self.inner.status(status),
}
}
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 {
inner: self.inner.header(key, value),
}
}
pub fn extension<T>(self, extension: T) -> Self
where
T: Clone + Any + Send + Sync + 'static,
{
Self {
inner: self.inner.extension(extension),
}
}
pub fn etag(self, etag: &str) -> ServerResult<Self> {
Ok(Self {
inner: self.inner.header(header::ETAG, HeaderValue::from_str(etag)?),
})
}
#[cfg(feature = "response-cookie")]
pub fn cookies(self, cookies: &[axum_extra::extract::cookie::Cookie<'_>]) -> ServerResult<Self> {
let mut resp = self.inner;
for cookie in cookies {
let header_value = cookie.encoded().to_string().parse::<HeaderValue>()?;
resp = resp.header(header::SET_COOKIE, header_value);
}
Ok(Self { inner: resp })
}
pub fn text(self, content: &str) -> ServerResult<Response> {
Ok(self
.inner
.header(
header::CONTENT_TYPE,
HeaderValue::from_static(mime::TEXT_PLAIN_UTF_8.as_ref()),
)
.body(Body::from(content.to_string()))?)
}
pub fn empty(self) -> ServerResult<Response> {
Ok(self.inner.body(Body::empty())?)
}
pub fn html(self, content: &str) -> ServerResult<Response> {
Ok(self
.inner
.header(
header::CONTENT_TYPE,
HeaderValue::from_static(mime::TEXT_HTML_UTF_8.as_ref()),
)
.body(Body::from(content.to_string()))?)
}
#[cfg(feature = "response-json")]
pub fn json<T>(self, item: T) -> ServerResult<Response>
where
T: serde::Serialize,
{
use bytes::{BufMut, BytesMut};
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
.inner
.header(
header::CONTENT_TYPE,
HeaderValue::from_static(mime::APPLICATION_JSON.as_ref()),
)
.body(body)?)
}
#[cfg(feature = "response-view")]
pub fn view<T>(self, template: &str, data: T) -> ServerResult<Response>
where
T: serde::Serialize,
{
let engine = soph_core::support::app().resolve::<soph_view::View>()?;
let html = engine.render(template, &tera::Context::from_serialize(data)?)?;
self.html(&html)
}
pub fn redirect(self, to: &str) -> ServerResult<Response> {
Ok(self
.inner
.status(StatusCode::SEE_OTHER)
.header(header::LOCATION, to)
.body(Body::empty())?)
}
}