Compare commits
4 Commits
d5eba9620c
...
738da0aac6
| Author | SHA1 | Date | |
|---|---|---|---|
|
738da0aac6
|
|||
|
76fac9b4cb
|
|||
|
4836108926
|
|||
|
d66871f2f5
|
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -2428,6 +2428,7 @@ dependencies = [
|
|||||||
"rand 0.10.1",
|
"rand 0.10.1",
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror 2.0.18",
|
"thiserror 2.0.18",
|
||||||
|
"tokio",
|
||||||
"tower-http 0.7.0",
|
"tower-http 0.7.0",
|
||||||
"tower-sessions-redis-store",
|
"tower-sessions-redis-store",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ rand = "0.10.1"
|
|||||||
serde = { version = "1.0.228", features = ["derive"] }
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
thiserror = "2.0.18"
|
thiserror = "2.0.18"
|
||||||
tower-http = { version = "0.7.0", optional = true, features = ["fs"] }
|
tower-http = { version = "0.7.0", optional = true, features = ["fs"] }
|
||||||
|
tokio = { version = "1.52.3", optional = true }
|
||||||
tower-sessions-redis-store = { version = "0.16.0", optional = true }
|
tower-sessions-redis-store = { version = "0.16.0", optional = true }
|
||||||
tracing = "0.1.44"
|
tracing = "0.1.44"
|
||||||
|
|
||||||
@@ -42,6 +43,7 @@ server = [
|
|||||||
"dep:dotenvy",
|
"dep:dotenvy",
|
||||||
"dep:fred",
|
"dep:fred",
|
||||||
"dep:pbkdf2",
|
"dep:pbkdf2",
|
||||||
|
"dep:tokio",
|
||||||
"dep:tower-http",
|
"dep:tower-http",
|
||||||
"dep:tower-sessions-redis-store",
|
"dep:tower-sessions-redis-store",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -28,10 +28,11 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "server")]
|
#[cfg(feature = "server")]
|
||||||
fn main() -> std::process::ExitCode {
|
#[tokio::main]
|
||||||
|
async fn main() -> std::process::ExitCode {
|
||||||
tracing_setup();
|
tracing_setup();
|
||||||
|
|
||||||
let Err(e) = server::main();
|
let Err(e) = server::main().await;
|
||||||
tracing::error!("Server main failed:\n{e}");
|
tracing::error!("Server main failed:\n{e}");
|
||||||
|
|
||||||
std::process::ExitCode::FAILURE
|
std::process::ExitCode::FAILURE
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
@@ -146,6 +147,14 @@ impl KeyValStoreConfig {
|
|||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
pub struct ServerConfig {
|
pub struct ServerConfig {
|
||||||
pub public_path: PathBuf,
|
pub public_path: PathBuf,
|
||||||
|
pub host: IpAddr,
|
||||||
|
pub port: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ServerConfig {
|
||||||
|
pub fn serve_addr(&self) -> SocketAddr {
|
||||||
|
SocketAddr::new(self.host, self.port)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
@@ -164,7 +173,16 @@ pub fn load_config() -> Result<Config, config::ConfigError> {
|
|||||||
let pkg_name = env!("CARGO_PKG_NAME");
|
let pkg_name = env!("CARGO_PKG_NAME");
|
||||||
|
|
||||||
config::Config::builder()
|
config::Config::builder()
|
||||||
.set_default("server.port", 8080)?
|
.set_default(
|
||||||
|
"server.port",
|
||||||
|
dioxus::cli_config::server_port().unwrap_or(8080),
|
||||||
|
)?
|
||||||
|
.set_default(
|
||||||
|
"server.host",
|
||||||
|
dioxus::cli_config::server_ip()
|
||||||
|
.unwrap_or(IpAddr::V4(Ipv4Addr::UNSPECIFIED))
|
||||||
|
.to_string(),
|
||||||
|
)?
|
||||||
.set_default("auth.open_signup", false)?
|
.set_default("auth.open_signup", false)?
|
||||||
.set_default("auth.cookies_secure", DEFAULT_COOKIES_SECURE)?
|
.set_default("auth.cookies_secure", DEFAULT_COOKIES_SECURE)?
|
||||||
.set_default("server.public_path", default_public_dir())?
|
.set_default("server.public_path", default_public_dir())?
|
||||||
|
|||||||
@@ -1,20 +1,21 @@
|
|||||||
use dioxus::{
|
use dioxus::{
|
||||||
fullstack::axum::{Router, middleware::from_fn},
|
cli_config,
|
||||||
|
fullstack::axum::{self, Router, middleware::from_fn},
|
||||||
|
prelude::{DioxusRouterExt, ServeConfig},
|
||||||
server::axum::Extension,
|
server::axum::Extension,
|
||||||
};
|
};
|
||||||
|
use tokio::net::TcpListener;
|
||||||
use tower_http::services::ServeFile;
|
use tower_http::services::ServeFile;
|
||||||
|
|
||||||
use crate::App;
|
use crate::App;
|
||||||
use crate::app::LOGO_ICO;
|
use crate::app::LOGO_ICO;
|
||||||
use crate::server::{
|
use crate::server::{
|
||||||
auth::build_auth_layer,
|
auth::build_auth_layer, config, database, key_val_store,
|
||||||
config::{self, Config},
|
|
||||||
database, key_val_store,
|
|
||||||
require_auth_mw::require_auth_middleware,
|
require_auth_mw::require_auth_middleware,
|
||||||
};
|
};
|
||||||
use crate::util::error::{Contextualize, Error, Result};
|
use crate::util::error::{Contextualize, Error, ErrorType, Result};
|
||||||
|
|
||||||
pub fn main() -> Result<std::convert::Infallible> {
|
pub async fn main() -> Result<std::convert::Infallible> {
|
||||||
if let Err(e) = dotenvy::dotenv() {
|
if let Err(e) = dotenvy::dotenv() {
|
||||||
tracing::warn!("Error reading .env: {e}");
|
tracing::warn!("Error reading .env: {e}");
|
||||||
}
|
}
|
||||||
@@ -32,15 +33,6 @@ pub fn main() -> Result<std::convert::Infallible> {
|
|||||||
std::env::set_var("DIOXUS_PUBLIC_PATH", config.server.public_path.clone());
|
std::env::set_var("DIOXUS_PUBLIC_PATH", config.server.public_path.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
// `Ok(...?)` is because `dioxus::serve` expects an `anyhow::Result`
|
|
||||||
dioxus::serve(move || {
|
|
||||||
let config = config.clone();
|
|
||||||
async move { Ok(router_setup(config).await?) }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set up the axum Router
|
|
||||||
async fn router_setup(config: Config) -> Result<Router> {
|
|
||||||
let db_pool = database::setup(config.database.connection_uri())
|
let db_pool = database::setup(config.database.connection_uri())
|
||||||
.await
|
.await
|
||||||
.err_context("Failed database setup")?;
|
.err_context("Failed database setup")?;
|
||||||
@@ -65,13 +57,42 @@ async fn router_setup(config: Config) -> Result<Router> {
|
|||||||
|
|
||||||
let auth_layer = build_auth_layer(db_pool.clone(), key_val_pool, config.auth.cookies_secure);
|
let auth_layer = build_auth_layer(db_pool.clone(), key_val_pool, config.auth.cookies_secure);
|
||||||
|
|
||||||
let router = dioxus::server::router(App)
|
#[cfg(debug_assertions)]
|
||||||
|
if let Some(dx_port) = cli_config::server_port()
|
||||||
|
&& dx_port != config.server.port
|
||||||
|
{
|
||||||
|
tracing::warn!(
|
||||||
|
"Your configured server port ({}) doesn't match the one specified from environment \
|
||||||
|
variables set by the Dioxus CLI ({dx_port}). If you are intending to use the dx tool, \
|
||||||
|
please do not specify a port in the configuration.",
|
||||||
|
config.server.port
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let addr = config.server.serve_addr();
|
||||||
|
|
||||||
|
tracing::info!("Setup complete, building router...");
|
||||||
|
|
||||||
|
let router = Router::new()
|
||||||
|
.serve_dioxus_application(ServeConfig::new(), App)
|
||||||
.layer(from_fn(require_auth_middleware))
|
.layer(from_fn(require_auth_middleware))
|
||||||
.layer(Extension(config))
|
.layer(Extension(config))
|
||||||
.layer(Extension(db_pool))
|
.layer(Extension(db_pool))
|
||||||
.layer(auth_layer)
|
.layer(auth_layer)
|
||||||
.nest_service("/favicon.ico", ServeFile::new(favicon_path));
|
.nest_service("/favicon.ico", ServeFile::new(favicon_path));
|
||||||
|
|
||||||
tracing::info!("Setup complete, returning Router...");
|
tracing::info!("Listening on {addr}...");
|
||||||
Ok(router)
|
let listener = TcpListener::bind(addr)
|
||||||
|
.await
|
||||||
|
.map_err(|e| ErrorType::HttpServer(e.to_string()))
|
||||||
|
.err_context(format!("Failed to bind to {addr}"))?;
|
||||||
|
|
||||||
|
axum::serve(listener, router)
|
||||||
|
.await
|
||||||
|
.map_err(|e| ErrorType::HttpServer(e.to_string()))
|
||||||
|
.err_context("HTTP server error")?;
|
||||||
|
|
||||||
|
Err(Error::new_here(ErrorType::HttpServer(
|
||||||
|
"axum::serve should never return".to_owned(),
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -327,6 +327,9 @@ pub enum ErrorType {
|
|||||||
// and Fred is only available on the server
|
// and Fred is only available on the server
|
||||||
#[error("Key-value store error: {0}")]
|
#[error("Key-value store error: {0}")]
|
||||||
KeyValStore(String),
|
KeyValStore(String),
|
||||||
|
|
||||||
|
#[error("HTTP server error: {0}")]
|
||||||
|
HttpServer(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ErrorType> for Error {
|
impl From<ErrorType> for Error {
|
||||||
|
|||||||
Reference in New Issue
Block a user