diff options
Diffstat (limited to 'dichroism/src')
-rw-r--r-- | dichroism/src/config.rs | 62 | ||||
-rw-r--r-- | dichroism/src/constants.rs | 1 | ||||
-rw-r--r-- | dichroism/src/main.rs | 99 | ||||
-rw-r--r-- | dichroism/src/migrations/photo_sets.sql | 8 | ||||
-rw-r--r-- | dichroism/src/migrations/products.sql | 12 | ||||
-rw-r--r-- | dichroism/src/result.rs | 2 |
6 files changed, 98 insertions, 86 deletions
diff --git a/dichroism/src/config.rs b/dichroism/src/config.rs index 2031ecc..225ee4c 100644 --- a/dichroism/src/config.rs +++ b/dichroism/src/config.rs @@ -1,32 +1,48 @@ -use crate::constants::DEFAULT_CONFIG; use crate::result::Result; -use once_cell::sync::Lazy; -use serde::Deserialize; -use std::env::var; -use std::fs::File; -use std::io::prelude::*; -use std::net::SocketAddr; -use toml::from_str; +use anyhow::{anyhow, Context}; +use std::{env::var, net::SocketAddr, path::PathBuf}; -pub static CONFIG_INSTANCE: Lazy<Config> = Lazy::new(|| { - Config::from_toml().unwrap_or_else(|e| { - eprintln!("Error parsing config: {}", e.to_string()); - std::process::exit(1); - }) -}); - -#[derive(Debug, Clone, Deserialize)] +#[derive(Debug, Clone)] pub struct Config { - pub db_url: String, - pub img_root: String, pub bind_addr: SocketAddr, + pub db_path: PathBuf, + pub img_path: PathBuf, } impl Config { - pub fn from_toml() -> Result<Self> { - let path = var("DICHROISM_CONFIG").unwrap_or_else(|_| String::from(DEFAULT_CONFIG)); - let mut config = String::new(); - File::open(path)?.read_to_string(&mut config)?; - Ok(from_str(&config)?) + pub fn from_env() -> Result<Self> { + let config = Self { + bind_addr: var("GL_BIND_ADDR") + .with_context(|| "Bind address missing.")? + .parse() + .with_context(|| "Failed to parse bind address.")?, + db_path: var("GL_DB_PATH") + .with_context(|| "Database path missing.")? + .parse() + .with_context(|| "Failed to parse database path.")?, + img_path: var("GL_IMG_PATH") + .with_context(|| "Image store path missing.")? + .parse() + .with_context(|| "Failed to parse image store path.")?, + }; + + if config.db_path.is_dir() { + Err(anyhow!(format!( + "Database path {:?} is not a regular file", + config.db_path + ))) + } else if !config.img_path.is_dir() { + Err(anyhow!(format!( + "Image store path {:?} is not a directory.", + config.img_path + ))) + } else if config.img_path.read_dir().is_err() { + Err(anyhow!(format!( + "Image store path {:?} is not readable.", + config.img_path + ))) + } else { + Ok(config) + } } } diff --git a/dichroism/src/constants.rs b/dichroism/src/constants.rs index 72a8de9..a973f3d 100644 --- a/dichroism/src/constants.rs +++ b/dichroism/src/constants.rs @@ -1,4 +1,3 @@ -pub const DEFAULT_CONFIG: &str = "./Dichroism.toml"; pub const PHOTO_FULLSIZE_XY: u32 = 1000; pub const PHOTO_BASE_XY: u32 = 640; pub const PHOTO_THUMBNAIL_XY: u32 = 300; diff --git a/dichroism/src/main.rs b/dichroism/src/main.rs index 6c76f0a..86de76f 100644 --- a/dichroism/src/main.rs +++ b/dichroism/src/main.rs @@ -1,66 +1,43 @@ -#[macro_use] -extern crate serde; -#[macro_use] -extern crate diesel; - -use actix_cors::Cors; -use actix_web::{middleware::Logger, App, HttpServer}; -use config::CONFIG_INSTANCE as CONFIG; -use diesel::prelude::SqliteConnection; -use diesel::r2d2::ConnectionManager; -use diesel::r2d2::Pool; -use listenfd::ListenFd; -use result::Result; +use anyhow::Context; +use axum::{http::StatusCode, routing::get_service, Router}; +use r2d2::Pool; +use r2d2_sqlite::SqliteConnectionManager; +use rusqlite::params; +use std::io::Error; +use tower_http::services::ServeDir; mod config; -mod constants; -mod dtos; -mod error; -mod handlers; -mod image_service; -mod models; -mod repo; mod result; -mod schema; -mod types; - -#[actix_web::main] -async fn main() -> Result<()> { - // Init logging - std::env::set_var("RUST_LOG", "actix_web=info"); - env_logger::init(); - - // Init DB connection pool - let manager = ConnectionManager::<SqliteConnection>::new(&CONFIG.db_url); - let pool = Pool::builder().build(manager)?; - - // Init application server - let mut server = HttpServer::new(move || { - // Init CORS policy - let cors = Cors::permissive(); - - App::new() - .data(pool.clone()) - .wrap(cors) - .wrap(Logger::default()) - .service(handlers::hello) - .service(handlers::get_products) - .service(handlers::patch_product) - .service(handlers::post_product) - .service(handlers::post_photo) - }); - - // If using listenfd, bind to it instead of the configured address to allow for cargo watch - // auto-reloading - let mut listenfd = ListenFd::from_env(); - server = if let Some(l) = listenfd - .take_tcp_listener(0) - .expect("Unable to grab TCP listener!") - { - server.listen(l)? - } else { - server.bind(CONFIG.bind_addr)? - }; - Ok(server.run().await?) +#[tokio::main] +async fn main() -> result::Result<()> { + // read config from environment + let config = config::Config::from_env()?; + + // start db connection pool + let manager = SqliteConnectionManager::file(&config.db_path); + let pool = Pool::new(manager).with_context(|| "Failed to create database connection pool.")?; + + // migrate/init db if empty + pool.get()? + .execute(include_str!("./migrations/photo_sets.sql"), params![])?; + pool.get()? + .execute(include_str!("./migrations/products.sql"), params![])?; + + let app = Router::new().nest( + "/static", + get_service(ServeDir::new("/zroot/gl/images")).handle_error(|error: Error| async move { + ( + StatusCode::INTERNAL_SERVER_ERROR, + format!("Unhandled internal error: {}", error), + ) + }), + ); + + axum::Server::bind(&config.bind_addr) + .serve(app.into_make_service()) + .await + .with_context(|| "Server error!")?; + + Ok(()) } diff --git a/dichroism/src/migrations/photo_sets.sql b/dichroism/src/migrations/photo_sets.sql new file mode 100644 index 0000000..a27c8ab --- /dev/null +++ b/dichroism/src/migrations/photo_sets.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS "photo_sets" ( + "id" INTEGER NOT NULL, + "base" TEXT NOT NULL, + "fullsize" TEXT NOT NULL, + "thumbnail" TEXT NOT NULL, + "original" TEXT NOT NULL, + PRIMARY KEY("id") +);
\ No newline at end of file diff --git a/dichroism/src/migrations/products.sql b/dichroism/src/migrations/products.sql new file mode 100644 index 0000000..0603a5c --- /dev/null +++ b/dichroism/src/migrations/products.sql @@ -0,0 +1,12 @@ +CREATE TABLE IF NOT EXISTS "products" ( + "id" INTEGER NOT NULL, + "photo_set" INTEGER NOT NULL, + "cents" INTEGER NOT NULL, + "quantity" INTEGER NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT NOT NULL, + "featured" INTEGER NOT NULL, + "category" TEXT NOT NULL, + PRIMARY KEY("id"), + FOREIGN KEY("photo_set") REFERENCES "photo_sets"("id") +);
\ No newline at end of file diff --git a/dichroism/src/result.rs b/dichroism/src/result.rs index 708451d..88e89cd 100644 --- a/dichroism/src/result.rs +++ b/dichroism/src/result.rs @@ -1 +1 @@ -pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>; +pub type Result<T> = anyhow::Result<T>; |