diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..0b64b58 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,85 @@ +use anyhow::Context; +use askama::Template; +use axum::{ + http::StatusCode, + response::{Html, IntoResponse, Response}, + routing::get, + Router, +}; +use tower_http::services::ServeDir; +use tracing::info; +use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; + +pub async fn run() -> anyhow::Result<()> { + tracing_subscriber::registry() + .with( + tracing_subscriber::EnvFilter::try_from_default_env() + .unwrap_or_else(|_| "achubb_backend".into()), + ) + .with(tracing_subscriber::fmt::layer()) + .init(); + info!("initializing router..."); + let assets_path = std::env::current_dir().unwrap(); + let port = 8000_u16; + let addr = std::net::SocketAddr::from(([0, 0, 0, 0], port)); + let api_router = Router::new().route("/hello", get(hello_from_the_server)); + let router = Router::new() + .nest("/api", api_router) + .route("/", get(hello)) + .route("/another-page", get(another_page)) + .nest_service( + "/assets", + ServeDir::new(format!("{}/assets", assets_path.to_str().unwrap())), + ); + info!("router initialized, now listening on port {}", port); + axum::Server::bind(&addr) + .serve(router.into_make_service()) + .await + .context("error while starting server")?; + Ok(()) +} + +async fn hello() -> impl IntoResponse { + let template = HelloTemplate {}; + HtmlTemplate(template) +} + +#[derive(Template)] +#[template(path = "hello.html")] +struct HelloTemplate; + +/// A wrapper type that we'll use to encapsulate HTML parsed by askama into valid HTML for axum to serve. +struct HtmlTemplate(T); + +/// Allows us to convert Askama HTML templates into valid HTML for axum to serve in the response. +impl IntoResponse for HtmlTemplate +where + T: Template, +{ + fn into_response(self) -> Response { + // Attempt to render the template with askama + match self.0.render() { + // If we're able to successfully parse and aggregate the template, serve it + Ok(html) => Html(html).into_response(), + // If we're not, return an error or some bit of fallback HTML + Err(err) => ( + StatusCode::INTERNAL_SERVER_ERROR, + format!("Failed to render template. Error: {}", err), + ) + .into_response(), + } + } +} + +async fn another_page() -> impl IntoResponse { + let template = AnotherPageTemplate {}; + HtmlTemplate(template) +} + +#[derive(Template)] +#[template(path = "another-page.html")] +struct AnotherPageTemplate; + +async fn hello_from_the_server() -> &'static str { + "Hello!" +} diff --git a/src/main.rs b/src/main.rs index b4bdbe4..0a64cdf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,86 +1,5 @@ -use anyhow::Context; -use askama::Template; -use axum::{ - http::StatusCode, - response::{Html, IntoResponse, Response}, - routing::get, - Router, -}; -use tower_http::services::ServeDir; -use tracing::info; -use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; - #[tokio::main] async fn main() -> anyhow::Result<()> { - tracing_subscriber::registry() - .with( - tracing_subscriber::EnvFilter::try_from_default_env() - .unwrap_or_else(|_| "achubb_backend".into()), - ) - .with(tracing_subscriber::fmt::layer()) - .init(); - info!("initializing router..."); - let assets_path = std::env::current_dir().unwrap(); - let port = 8000_u16; - let addr = std::net::SocketAddr::from(([0, 0, 0, 0], port)); - let api_router = Router::new().route("/hello", get(hello_from_the_server)); - let router = Router::new() - .nest("/api", api_router) - .route("/", get(hello)) - .route("/another-page", get(another_page)) - .nest_service( - "/assets", - ServeDir::new(format!("{}/assets", assets_path.to_str().unwrap())), - ); - info!("router initialized, now listening on port {}", port); - axum::Server::bind(&addr) - .serve(router.into_make_service()) - .await - .context("error while starting server")?; + achubb_backend::run().await?; Ok(()) } - -async fn hello() -> impl IntoResponse { - let template = HelloTemplate {}; - HtmlTemplate(template) -} - -#[derive(Template)] -#[template(path = "hello.html")] -struct HelloTemplate; - -/// A wrapper type that we'll use to encapsulate HTML parsed by askama into valid HTML for axum to serve. -struct HtmlTemplate(T); - -/// Allows us to convert Askama HTML templates into valid HTML for axum to serve in the response. -impl IntoResponse for HtmlTemplate -where - T: Template, -{ - fn into_response(self) -> Response { - // Attempt to render the template with askama - match self.0.render() { - // If we're able to successfully parse and aggregate the template, serve it - Ok(html) => Html(html).into_response(), - // If we're not, return an error or some bit of fallback HTML - Err(err) => ( - StatusCode::INTERNAL_SERVER_ERROR, - format!("Failed to render template. Error: {}", err), - ) - .into_response(), - } - } -} - -async fn another_page() -> impl IntoResponse { - let template = AnotherPageTemplate {}; - HtmlTemplate(template) -} - -#[derive(Template)] -#[template(path = "another-page.html")] -struct AnotherPageTemplate; - -async fn hello_from_the_server() -> &'static str { - "Hello!" -}