plant/back/src/main.rs

77 lines
2.3 KiB
Rust

use std::str::FromStr;
use axum::{
extract::State, http::StatusCode, routing::post, Json, Router
};
use sqlx::{Row, sqlite::{SqliteConnectOptions, SqlitePoolOptions}, Pool, Sqlite};
#[derive(Clone)]
struct ST {
db: Pool<Sqlite>
}
#[tokio::main]
async fn main() {
const ADDR : &str = "localhost:3013";
const DB_ADDR : &str = "sqlite://./db.sqlite";
tracing_subscriber::fmt::init();
let listener = tokio::net::TcpListener::bind(ADDR)
.await.expect(&format!("Could not bind on {ADDR}"));
println!("Listening on http://{ADDR}");
let opts = SqliteConnectOptions::from_str(DB_ADDR)
.expect("Could not parse database address")
.create_if_missing(true);
let db = SqlitePoolOptions::new()
.max_connections(5)
.connect_with(opts)
.await.expect("Could not open database");
println!("Opened sqlite database on {DB_ADDR}");
sqlx::query(r#"
CREATE TABLE IF NOT EXISTS Counter (
id INTEGER PRIMARY KEY check (id = 0),
value INTEGER NOT NULL
);
INSERT OR IGNORE INTO Counter (id, value) VALUES (0, 0);
"#).execute(&db).await.expect("Could not initialize database");
let state : ST = ST { db };
let app = Router::new()
.route("/api/echo", post(echo))
.route("/api/get_counter", post(get_counter))
.route("/api/set_counter", post(set_counter))
.with_state(state);
axum::serve(listener, app)
.await.expect("Unable to start app");
}
async fn get_counter(State(ST { db }): State<ST>) -> (StatusCode, String) {
let row = sqlx::query("SELECT * FROM Counter")
.fetch_one(&db)
.await.expect("no counter in db");
let response : u32 = row.get("value");
(StatusCode::OK, response.to_string())
}
async fn set_counter(State(ST { db }): State<ST>, Json(body) : Json<String>) -> (StatusCode, String) {
sqlx::query(match &*body {
"add" => "UPDATE Counter SET value = value + 1",
"sub" => "UPDATE Counter SET value = value - 1",
_ => return (StatusCode::BAD_REQUEST, "invalid action".to_string()),
}).execute(&db).await.expect("database write error");
get_counter(State(ST { db })).await
}
async fn echo(body : String) -> (StatusCode, String) {
(StatusCode::OK, body)
}