Skip to main content

rango_core/
view.rs

1//! Views: request handlers and response helpers.
2
3use askama::Template;
4use axum::{
5    response::{Html, IntoResponse, Redirect},
6    routing::{MethodRouter, get},
7};
8use serde::Serialize;
9
10use crate::error::Error;
11
12pub use axum::extract::Json;
13
14/// Incoming axum request.
15pub type Request = axum::extract::Request;
16/// Outgoing axum response.
17pub type Response = axum::response::Response;
18
19/// HTML response with the given body.
20pub fn html(body: impl Into<String>) -> Response {
21    Html(body.into()).into_response()
22}
23
24/// JSON response from a serializable value.
25pub fn json(data: impl Serialize) -> Response {
26    Json(data).into_response()
27}
28
29/// HTML response from rendering an askama template.
30pub fn render<T: Template>(template: T) -> Result<Response, Error> {
31    Ok(Html(template.render()?).into_response())
32}
33
34/// Redirect response to the given location.
35pub fn redirect(to: &str) -> Response {
36    Redirect::to(to).into_response()
37}
38
39/// A request handler producing a response or an error.
40pub trait View: Clone + Send + Sync + 'static {
41    /// Run this view against the request.
42    fn call(self, req: Request) -> Result<Response, Error>;
43}
44
45impl<F> View for F
46where
47    F: Fn(Request) -> Result<Response, Error> + Clone + Send + Sync + 'static,
48{
49    fn call(self, req: Request) -> Result<Response, Error> {
50        self(req)
51    }
52}
53
54/// Axum method router for a view closure.
55pub fn get_view<V: View>(view: V) -> MethodRouter {
56    get(move |req: Request| async move { view.call(req).into_response() })
57}