Compare commits
10 commits
Author | SHA1 | Date | |
---|---|---|---|
68e8a9cd6e | |||
fa690d48bd | |||
f1facae8a2 | |||
a2536696ce | |||
634eefb8e6 | |||
|
122f33eae9 | ||
32f0ed27a7 | |||
cab6b92c52 | |||
bf627f6003 | |||
|
9496d107f9 |
10 changed files with 323 additions and 55 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,4 +1,2 @@
|
|||
.idea
|
||||
db/*
|
||||
backend/target/*
|
||||
|
||||
|
|
0
server/.gitignore → backend/.gitignore
vendored
0
server/.gitignore → backend/.gitignore
vendored
24
backend/Cargo.toml
Normal file
24
backend/Cargo.toml
Normal file
|
@ -0,0 +1,24 @@
|
|||
[package]
|
||||
name = "server"
|
||||
version = "1.0.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
# rust
|
||||
actix-web ="4"
|
||||
actix-files = "*"
|
||||
utoipa-swagger-ui = { version = "3", features = ["actix-web"] }
|
||||
|
||||
# db-connection
|
||||
sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "sqlite"]}
|
||||
tokio = { version = "1.20.0", features = ["macros"]}
|
||||
|
||||
[[bin]]
|
||||
name = "webserver"
|
||||
path = "src/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "db_access"
|
||||
path = "src/main_db.rs"
|
19
backend/openapi.json
Normal file
19
backend/openapi.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"title": "My API",
|
||||
"version": "1.0"
|
||||
},
|
||||
"paths": {
|
||||
"/example": {
|
||||
"get": {
|
||||
"summary": "Get example",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
25
backend/readme.md
Normal file
25
backend/readme.md
Normal file
|
@ -0,0 +1,25 @@
|
|||
# installation
|
||||
|
||||
Rustup gets you the ability to install rust in any version, from stable to cutting edge.
|
||||
|
||||
## Linux, macos (step 1)
|
||||
|
||||
use apt, pacman, curl, brew or whatever, to install _rustup_.
|
||||
|
||||
## windows (alternate step 1)
|
||||
|
||||
choco install -y rustup
|
||||
|
||||
## Always (steps 2 and so on)
|
||||
|
||||
- `rustup-init.sh` (Windows: rustup-init.ex, e.g. %AppData%\Local\Temp\chocolatey\rustup.install\1.25.1\rustup-init.exe)
|
||||
- select a good match in the dialog of this CLI installer,
|
||||
- i.e. stable and default amount of features should be fine
|
||||
- rust comes with `cargo` as a ``crate'' manager for package installation
|
||||
|
||||
## Get dependencies and run
|
||||
|
||||
```shell
|
||||
cargo build # gets dependencies from Cargo.toml
|
||||
cargo run # re-runs on (some?) changes
|
||||
```
|
30
backend/src/main.rs
Normal file
30
backend/src/main.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
use actix_web::{web, App, HttpResponse, HttpServer};
|
||||
use utoipa_swagger_ui::{get_swagger_ui, DefaultConfig};
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
HttpServer::new(|| {
|
||||
let swagger_config = DefaultConfig::new("http://localhost:8080", "/openapi.json");
|
||||
App::new()
|
||||
.service(get_swagger_ui(&swagger_config))
|
||||
.route("/openapi.json", web::get().to(get_openapi_spec))
|
||||
})
|
||||
.bind("0.0.0.0:8080")?
|
||||
.run()
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_openapi_spec() -> HttpResponse {
|
||||
let openapi_spec = r#"
|
||||
{
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"title": "Dummy API",
|
||||
"version": "1.0"
|
||||
},
|
||||
"paths": {}
|
||||
}
|
||||
"#;
|
||||
|
||||
HttpResponse::Ok().body(openapi_spec)
|
||||
}
|
225
backend/src/main_db.rs
Normal file
225
backend/src/main_db.rs
Normal file
|
@ -0,0 +1,225 @@
|
|||
use sqlx::{migrate::MigrateDatabase, FromRow, Sqlite, SqlitePool};
|
||||
use std::io;
|
||||
|
||||
const DB_URL: &str = "sqlite://db/test.db";
|
||||
|
||||
const COMMANDS :[(i32, &str, &str); 5] = [
|
||||
(0, "createDB", "creates the database if not already."),
|
||||
(1, "initDB", "initializes the data of the db with given file"),
|
||||
(2, "connect", "connecting to the db."),
|
||||
(3, "execute sql", "execute SQL that is entered"),
|
||||
(4, "disconnect", "closing connection to db."),
|
||||
];
|
||||
|
||||
#[derive(Clone, FromRow, Debug)]
|
||||
struct User {
|
||||
id: i64,
|
||||
name: String,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
// game loop
|
||||
|
||||
let mut db: Option<SqlitePool> = None;
|
||||
|
||||
loop {
|
||||
println!("What do you want to do?\n");
|
||||
print_commands();
|
||||
println!("");
|
||||
|
||||
let mut choice = String::new();
|
||||
|
||||
io::stdin()
|
||||
.read_line(&mut choice)
|
||||
.expect("Failed to read line");
|
||||
|
||||
let choice: u32 = choice
|
||||
.trim()
|
||||
.parse()
|
||||
.expect("Please type a number!");
|
||||
|
||||
match choice {
|
||||
0 => create_db().await,
|
||||
1 => init_db(),
|
||||
2 => db = connect_db().await,
|
||||
3 => execute_sql(&db).await,
|
||||
4 => {
|
||||
db.clone().unwrap().close().await;
|
||||
db = None;
|
||||
}
|
||||
_ => println!("This Command does not exists")
|
||||
}
|
||||
println!("");
|
||||
}
|
||||
}
|
||||
|
||||
fn print_commands() {
|
||||
|
||||
for command in COMMANDS {
|
||||
let (num, name, desc) = command;
|
||||
|
||||
println!("{num}. {name} \t{desc}");
|
||||
}
|
||||
}
|
||||
|
||||
async fn create_db() {
|
||||
// TODO
|
||||
|
||||
if !Sqlite::database_exists(DB_URL).await.unwrap_or(false) {
|
||||
println!("Creating database {}", DB_URL);
|
||||
match Sqlite::create_database(DB_URL).await {
|
||||
Ok(_) => println!("Create db success"),
|
||||
Err(error) => panic!("error: {}", error),
|
||||
}
|
||||
} else {
|
||||
println!("database already exists");
|
||||
}
|
||||
}
|
||||
|
||||
fn init_db() {
|
||||
todo!();
|
||||
}
|
||||
|
||||
async fn connect_db() -> Option<SqlitePool>{
|
||||
|
||||
let db = Some(SqlitePool::connect(DB_URL).await.unwrap());
|
||||
println!("Connected to DB.");
|
||||
return db;
|
||||
}
|
||||
|
||||
async fn execute_sql(opt_db: &Option<SqlitePool>) {
|
||||
|
||||
if opt_db.is_none() {
|
||||
println!("There is no active connection to the db.");
|
||||
return;
|
||||
}
|
||||
|
||||
let db = opt_db.clone().unwrap();
|
||||
|
||||
loop {
|
||||
let mut choice = String::new();
|
||||
|
||||
println!("0: freely (danger!)\n1: create \n2: insert\n3: query\n4: delete\n5: drop table");
|
||||
io::stdin()
|
||||
.read_line(&mut choice)
|
||||
.expect("Failed to read line");
|
||||
|
||||
let choice: u32 = choice
|
||||
.trim()
|
||||
.parse()
|
||||
.expect("Please type a number!");
|
||||
|
||||
match choice {
|
||||
0 => freely(&db).await,
|
||||
1 => create(&db).await,
|
||||
2 => insert(&db).await,
|
||||
3 => query(&db).await,
|
||||
4 => delete(&db).await,
|
||||
5 => drop_table(&db).await,
|
||||
_ => {
|
||||
println!("This Command does not exists");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn create(db : &SqlitePool) {
|
||||
let result = sqlx::query(
|
||||
"CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER NOT NULL PRIMARY KEY,
|
||||
name WARCHAR(250) NOT NULL
|
||||
);")
|
||||
.execute(db)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
println!("Create user table result: {:?}", result);
|
||||
}
|
||||
|
||||
async fn insert(db : &SqlitePool) {
|
||||
|
||||
let mut name = String::new();
|
||||
|
||||
println!("insert what name?");
|
||||
io::stdin()
|
||||
.read_line(&mut name)
|
||||
.expect("Failed to read line");
|
||||
|
||||
let result = sqlx::query("INSERT INTO users (name) VALUES (?)")
|
||||
.bind(name)
|
||||
.execute(db)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
println!("result: {:?}", result);
|
||||
}
|
||||
|
||||
async fn query(db : &SqlitePool) {
|
||||
|
||||
let data = match sqlx::query_as::<_, User>("SELECT id, name FROM users")
|
||||
.fetch_all(db)
|
||||
.await {
|
||||
Ok(d) => d,
|
||||
Err(_) => {
|
||||
println!("something went wrong.");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
for user in data {
|
||||
println!("[{}] name: {}", user.id, &user.name);
|
||||
}
|
||||
}
|
||||
|
||||
async fn delete(db : &SqlitePool) {
|
||||
|
||||
let mut name = String::new();
|
||||
|
||||
println!("delete what name?");
|
||||
io::stdin()
|
||||
.read_line(&mut name)
|
||||
.expect("Failed to read line");
|
||||
|
||||
let result = match sqlx::query("DELETE FROM users WHERE name=$1")
|
||||
.bind(name)
|
||||
.execute(db)
|
||||
.await {
|
||||
Ok(r) => Some(r),
|
||||
Err(_) => {
|
||||
println!("user could not be deleted.");
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
if result.is_some() {
|
||||
println!("result: {:?}", result.unwrap());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async fn freely(db : &SqlitePool) {
|
||||
|
||||
let mut sql = String::new();
|
||||
|
||||
io::stdin()
|
||||
.read_line(&mut sql)
|
||||
.expect("Failed to read line");
|
||||
|
||||
let result = sqlx::query(&sql)
|
||||
.execute(db)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
println!("result: {:?}", result);
|
||||
}
|
||||
|
||||
async fn drop_table(db : &SqlitePool) {
|
||||
let result = sqlx::query("DROP TABLE users;")
|
||||
.execute(db)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
println!("result: {:?}", result);
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
[package]
|
||||
name = "server"
|
||||
version = "1.0.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
actix-web ="4"
|
||||
utoipa = { version = "3", features = ["actix_extras"] }
|
|
@ -1,15 +0,0 @@
|
|||
# installation
|
||||
|
||||
## windows (step 1)
|
||||
|
||||
choco install -y
|
||||
|
||||
## Linux, macos (alernate step 1)
|
||||
|
||||
use apt, pacman, curl, brew or whatever.
|
||||
|
||||
## Always (steps 2 and so on)
|
||||
|
||||
- `rustup-init.sh` (Windows: rustup-init.ex, e.g. %AppData%\Local\Temp\chocolatey\rustup.install\1.25.1\rustup-init.exe)
|
||||
- select a good match in the dialog of this CLI installer
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
|
||||
|
||||
#[get("/")]
|
||||
async fn hello() -> impl Responder {
|
||||
HttpResponse::Ok().body("Hello world!")
|
||||
}
|
||||
|
||||
#[post("/echo")]
|
||||
async fn echo(req_body: String) -> impl Responder {
|
||||
HttpResponse::Ok().body(req_body)
|
||||
}
|
||||
|
||||
async fn manual_hello() -> impl Responder {
|
||||
HttpResponse::Ok().body("Hey there!")
|
||||
}
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
HttpServer::new(|| {
|
||||
App::new()
|
||||
.service(hello)
|
||||
.service(echo)
|
||||
.route("/hey", web::get().to(manual_hello))
|
||||
})
|
||||
.bind(("127.0.0.1", 8080))?
|
||||
.run()
|
||||
.await
|
||||
}
|
Loading…
Reference in a new issue