diff --git a/README.md b/README.md index 1d42f27..16300e8 100644 --- a/README.md +++ b/README.md @@ -28,11 +28,12 @@ postgres=# ALTER DATABASE crawlnicle OWNER TO crawlnicle; directory with the contents: ``` +RUST_LOG=crawlnicle=debug,cli=debug,lib=debug,tower_http=debug,sqlx=debug HOST=127.0.0.1 PORT=3000 DATABASE_URL=postgresql://crawlnicle:@localhost/crawlnicle DATABASE_MAX_CONNECTIONS=5 -RUST_LOG=crawlnicle=debug,cli=debug,lib=debug,tower_http=debug,sqlx=debug +TITLE=crawlnicle ``` 4. Install diff --git a/src/config.rs b/src/config.rs index a5586be..0f64dc1 100644 --- a/src/config.rs +++ b/src/config.rs @@ -6,6 +6,7 @@ pub struct Config { pub database_max_connections: u32, pub host: String, pub port: u16, + pub title: String, } impl Config { @@ -14,12 +15,14 @@ impl Config { let database_max_connections = std::env::var("DATABASE_MAX_CONNECTIONS").context("DATABASE_MAX_CONNECTIONS not set")?.parse()?; let host = std::env::var("HOST").context("HOST not set")?; let port = std::env::var("PORT").context("PORT not set")?.parse()?; + let title = std::env::var("TITLE").context("TITLE not set")?; Ok(Config { database_url, database_max_connections, host, port, + title, }) } } diff --git a/src/lib.rs b/src/lib.rs index 6bb3fcd..a25133b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,3 +4,4 @@ pub mod handlers; pub mod jobs; pub mod models; pub mod partials; +pub mod state; diff --git a/src/main.rs b/src/main.rs index 9b57efa..a0924eb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ use std::path::Path; use anyhow::Result; use axum::{ routing::{get, post}, - Router, Extension, + Router, }; use dotenvy::dotenv; use notify::Watcher; @@ -15,6 +15,7 @@ use tracing::debug; use lib::config; use lib::handlers; +use lib::state::AppState; #[tokio::main] async fn main() -> Result<()> { @@ -41,9 +42,11 @@ async fn main() -> Result<()> { .route("/api/v1/entry/:id", get(handlers::api::entry::get)) .route("/", get(handlers::home::get)) .route("/feeds", get(handlers::feeds::get)) - .with_state(pool) - .layer(ServiceBuilder::new().layer(TraceLayer::new_for_http())) - .layer(Extension(config)); + .with_state(AppState { + pool, + config, + }) + .layer(ServiceBuilder::new().layer(TraceLayer::new_for_http())); #[cfg(debug_assertions)] { diff --git a/src/partials/layout.rs b/src/partials/layout.rs index f641c14..63205ca 100644 --- a/src/partials/layout.rs +++ b/src/partials/layout.rs @@ -1,25 +1,33 @@ use axum::{ - async_trait, - extract::FromRequestParts, - http::request::Parts, - response::{Html, IntoResponse, Response}, + async_trait, + extract::{FromRef, FromRequestParts, State}, + http::request::Parts, + response::{Html, IntoResponse, Response}, }; -use maud::{DOCTYPE, html, Markup}; +use maud::{html, Markup, DOCTYPE}; +use crate::config::Config; use crate::partials::header::header; -pub struct Layout; +pub struct Layout { + pub title: String, +} #[async_trait] impl FromRequestParts for Layout where S: Send + Sync, + Config: FromRef, { - type Rejection = std::convert::Infallible; + type Rejection = Response; - async fn from_request_parts(_parts: &mut Parts, _state: &S) -> Result { - // extract whatever your layout needs - Ok(Self {}) + async fn from_request_parts(parts: &mut Parts, state: &S) -> Result { + let State(config) = State::::from_request_parts(parts, state) + .await + .map_err(|err| err.into_response())?; + Ok(Self { + title: config.title, + }) } } @@ -40,7 +48,8 @@ impl Layout { (template) } } - }.into_string(); + } + .into_string(); Html(with_layout).into_response() } diff --git a/src/state.rs b/src/state.rs new file mode 100644 index 0000000..a08c9e4 --- /dev/null +++ b/src/state.rs @@ -0,0 +1,22 @@ +use axum::extract::FromRef; +use sqlx::PgPool; + +use crate::config::Config; + +#[derive(Clone)] +pub struct AppState { + pub pool: PgPool, + pub config: Config, +} + +impl FromRef for PgPool { + fn from_ref(state: &AppState) -> Self { + state.pool.clone() + } +} + +impl FromRef for Config { + fn from_ref(state: &AppState) -> Self { + state.config.clone() + } +}