77 lines
2.3 KiB
Rust
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)
|
|
}
|