stateful warp controllers

This commit is contained in:
blek 2023-10-01 10:14:35 +10:00
parent 61772e3552
commit 2fa3f14597
Signed by: blek
GPG Key ID: 14546221E3595D0C
9 changed files with 94 additions and 11 deletions

33
filed/Cargo.lock generated
View File

@ -130,6 +130,16 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "combine"
version = "4.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4"
dependencies = [
"bytes",
"memchr",
]
[[package]]
name = "cpufeatures"
version = "0.2.9"
@ -215,6 +225,7 @@ dependencies = [
"femme",
"futures-util",
"log",
"redis",
"tokio",
"warp",
]
@ -696,6 +707,22 @@ dependencies = [
"getrandom",
]
[[package]]
name = "redis"
version = "0.23.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f49cdc0bb3f412bf8e7d1bd90fe1d9eb10bc5c399ba90973c14662a27b3f8ba"
dependencies = [
"combine",
"itoa",
"percent-encoding",
"ryu",
"sha1_smol",
"socket2 0.4.9",
"tokio",
"url",
]
[[package]]
name = "rustc-demangle"
version = "0.1.23"
@ -786,6 +813,12 @@ dependencies = [
"digest",
]
[[package]]
name = "sha1_smol"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
[[package]]
name = "slab"
version = "0.4.9"

View File

@ -12,5 +12,6 @@ dotenvy = "0.15.7"
femme = "2.2.1"
futures-util = "0.3.28"
log = "0.4.20"
redis = { version = "0.23.3", features = ["tokio"] }
tokio = { version = "1.32.0", features = ["rt", "macros", "rt-multi-thread"] }
warp = "0.3.6"

12
filed/src/db.rs Normal file
View File

@ -0,0 +1,12 @@
/*
db.rs - The database adapter
*/
use redis::{Client, RedisError};
use crate::env::Env;
pub fn redis_conn(env: Env) -> Result<Client, RedisError> {
log::info!("Connecting to redis DB on {}", env.redis.host);
redis::Client::open(format!("redis://{}:{}/", env.redis.host, env.redis.port))
}

View File

@ -5,9 +5,19 @@
use std::{env::var, net::SocketAddr};
#[derive(Debug, Clone)]
pub struct Redis {
pub pass: String,
pub host: String,
pub port: u16,
pub prefix: String
}
#[derive(Debug, Clone)]
pub struct Env {
pub logging: bool,
pub listen: SocketAddr
pub listen: SocketAddr,
pub redis: Redis,
}
fn get_var<T: Into<String>, O: From<String>>(name: T) -> Result<O, String> {
@ -23,7 +33,13 @@ pub fn loadenv() -> Result<Env, Box<dyn std::error::Error>> {
Ok(
Env {
logging: get_var::<&str, String>("APP_LOGGING")?.to_lowercase() == "true",
listen: get_var::<&str, String>("APP_HOST")?.parse::<SocketAddr>().unwrap()
listen: get_var::<&str, String>("APP_HOST")?.parse::<SocketAddr>().unwrap(),
redis: Redis {
pass: get_var("REDIS_PASS")?,
host: get_var("REDIS_HOST")?,
port: get_var::<&str, String>("REDIS_PORT")?.parse().unwrap(),
prefix: get_var("REDIS_PREFIX")?
}
}
)
}

View File

@ -4,6 +4,7 @@
mod env;
mod web;
mod db;
#[tokio::main]
async fn main() {

View File

@ -5,11 +5,13 @@
use std::collections::HashMap;
use warp::{Filter, reply::{Html, Reply}, reject::Rejection, filters::multipart::FormData};
use warp::{Filter, reply::Reply, reject::Rejection, filters::multipart::FormData};
use futures_util::TryStreamExt;
use bytes::BufMut;
pub async fn upload(form: FormData) -> Result<Box<dyn Reply>, Rejection> {
use super::state::SharedState;
pub async fn upload(form: FormData, _state: SharedState) -> Result<Box<dyn Reply>, Rejection> {
let params: HashMap<String, String> = form.and_then(|mut field| async move {
let mut bytes: Vec<u8> = vec![];
@ -23,8 +25,10 @@ pub async fn upload(form: FormData) -> Result<Box<dyn Reply>, Rejection> {
Ok(Box::new(warp::reply::json(&params)))
}
pub fn get_routes() -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
pub fn get_routes(state: SharedState) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
warp::post().and(
warp::multipart::form().and_then(upload)
warp::multipart::form()
.and(warp::any().map(move || state.clone()))
.and_then(upload)
)
}

View File

@ -10,13 +10,16 @@ use crate::env::Env;
mod pages;
mod forms;
mod state;
pub fn routes() -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
use state::SharedState;
pub fn routes(state: SharedState) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
let staticpath = current_dir().unwrap();
let staticpath = staticpath.to_str().unwrap().to_string() + "/static";
pages::get_routes()
.or(forms::get_routes())
pages::get_routes(state.clone())
.or(forms::get_routes(state))
.or(warp::fs::dir(staticpath.to_string()))
}
@ -27,5 +30,9 @@ pub async fn serve(env: Env) {
log::info!("Listening on {}", env.listen.to_string());
warp::serve(routes()).run(env.listen).await;
let state = SharedState {
redis_cli: crate::db::redis_conn(env.clone()).unwrap()
};
warp::serve(routes(state)).run(env.listen).await;
}

View File

@ -5,6 +5,8 @@
use warp::{reply::{Reply, Html}, Filter, reject::Rejection};
use askama::Template;
use super::state::SharedState;
#[derive(Template)]
#[template( path = "index.html" )]
struct Index {}
@ -14,7 +16,7 @@ pub fn index() -> Html<String> {
warp::reply::html(rendered.render().unwrap())
}
pub fn get_routes() -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
pub fn get_routes(_state: SharedState) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
let index_r = warp::path::end().map(index);
warp::any().and(index_r)

7
filed/src/web/state.rs Normal file
View File

@ -0,0 +1,7 @@
use redis::Client;
#[derive(Debug, Clone)]
pub struct SharedState {
pub redis_cli: Client
}