feat: add router

This commit is contained in:
Kristofers Solo 2025-06-21 16:15:50 +03:00
parent 3e190e3cca
commit 85765bb3b0
Signed by: kristoferssolo
GPG Key ID: 8687F2D3EEE6F0ED
7 changed files with 64 additions and 47 deletions

View File

@ -1,4 +1,4 @@
mod configuration;
mod routes;
mod startup;
mod telemetry;
pub mod configuration;
pub mod routes;
pub mod startup;
pub mod telemetry;

View File

@ -1,30 +1,16 @@
use app::*;
use axum::Router;
use leptos::logging::log;
use leptos::prelude::*;
use leptos_axum::{LeptosRoutes, generate_route_list};
use server::{
configuration::get_config,
startup::Application,
telemetry::{get_subscriber, init_subscriber},
};
use std::io::Error;
#[tokio::main]
async fn main() {
let conf = get_configuration(None).unwrap();
let addr = conf.leptos_options.site_addr;
let leptos_options = conf.leptos_options;
// Generate the list of routes in your Leptos App
let routes = generate_route_list(App);
let app = Router::new()
.leptos_routes(&leptos_options, routes, {
let leptos_options = leptos_options.clone();
move || shell(leptos_options.clone())
})
.fallback(leptos_axum::file_and_error_handler(shell))
.with_state(leptos_options);
// run our app with hyper
// `axum::Server` is a re-export of `hyper::Server`
log!("listening on http://{}", &addr);
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
axum::serve(listener, app.into_make_service())
.await
.unwrap();
async fn main() -> Result<(), Error> {
let subscriber = get_subscriber("kristofersxyz", "info", std::io::stdout);
init_subscriber(subscriber);
let config = get_config().expect("Failed to read configuation.");
let application = Application::build(&config).await?;
application.start().await?;
Ok(())
}

View File

@ -1,6 +1,27 @@
use crate::startup::AppState;
use axum::Router;
use app::{App, shell};
use axum::{Router, extract::State, http::StatusCode, response::IntoResponse, routing::get};
use leptos_axum::{LeptosRoutes, generate_route_list};
pub fn route(state: AppState) -> Router {
todo!()
let leptos_options = state.leptos_options.clone();
let routes = generate_route_list(App);
let leptos_router = Router::new()
.leptos_routes(&leptos_options, routes, {
let leptos_options = leptos_options.clone();
move || shell(leptos_options.clone())
})
.fallback(leptos_axum::file_and_error_handler(shell))
.with_state(leptos_options);
let api_router = Router::new()
.route("/health_check", get(health_check))
.with_state(state);
leptos_router.merge(api_router)
}
async fn health_check(State(_state): State<AppState>) -> impl IntoResponse {
StatusCode::OK
}

View File

@ -2,9 +2,12 @@ use crate::{
configuration::{DatabaseSettings, Settings},
routes::route,
};
use leptos::config::{LeptosOptions, get_configuration};
use sqlx::{PgPool, postgres::PgPoolOptions};
use std::{
io::{Error, ErrorKind},
net::SocketAddr,
ops::Deref,
sync::Arc,
};
use tokio::{net::TcpListener, task::JoinHandle};
@ -13,6 +16,8 @@ use tracing::{error, info};
/// Shared application state.
pub struct App {
pub pool: PgPool,
pub leptos_options: LeptosOptions,
pub addr: SocketAddr,
}
/// Type alias for the shared application state wrapped in `Arc`.
@ -20,7 +25,6 @@ pub type AppState = Arc<App>;
/// Represents the application, including its server and configuration.
pub struct Application {
port: u16,
server: Option<JoinHandle<Result<(), Error>>>,
}
@ -30,20 +34,25 @@ impl Application {
/// This method initializes the database connection pool, binds the server
/// to the specified address, and prepares the application for startup.
pub async fn build(config: &Settings) -> Result<Self, Error> {
let conf = get_configuration(None).unwrap();
let addr = conf.leptos_options.site_addr;
let leptos_options = conf.leptos_options;
// Initialize the database connection pool
let pool = get_connection_pool(&config.database);
info!("Database connection pool initialized.");
// Bind the server to the specified address
let addr = format!("{}:{}", config.application.host, config.application.port);
let listener = TcpListener::bind(addr).await?;
let port = listener.local_addr().unwrap().port();
info!("Server listening on port {}", port);
// Create the shared application state
let app_state = App { pool }.into();
let app_state = App {
pool,
leptos_options: leptos_options.clone(),
addr,
}
.into();
// Spawn the server
info!("listening on http://{}", &addr);
let listener = TcpListener::bind(addr).await?;
let server = tokio::spawn(async move {
axum::serve(listener, route(app_state)).await.map_err(|e| {
error!("Server error: {}", e);
@ -52,16 +61,10 @@ impl Application {
});
Ok(Self {
port,
server: Some(server),
})
}
/// Get the port the server is listening on.
pub fn port(&self) -> u16 {
self.port
}
pub async fn start(self) -> Result<(), Error> {
self.server
.ok_or_else(|| Error::new(ErrorKind::Other, "Server was not initialized."))?
@ -75,3 +78,10 @@ impl Application {
fn get_connection_pool(config: &DatabaseSettings) -> PgPool {
PgPoolOptions::new().connect_lazy_with(config.with_db())
}
impl Deref for App {
type Target = LeptosOptions;
fn deref(&self) -> &Self::Target {
&self.leptos_options
}
}