Add docker compose files & Fix routes

This commit is contained in:
2025-11-13 02:32:35 +03:00
parent f9a1609e0c
commit 86d7545f7c
4 changed files with 60 additions and 62 deletions

1
.gitignore vendored
View File

@ -1,7 +1,6 @@
# my gitignore
todo.md
.env
compose.yaml
# ---> Rust
# Generated by Cargo

9
compose.yaml Normal file
View File

@ -0,0 +1,9 @@
services:
database:
image: docker.io/postgres:17
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
ports:
- ${POSTGRES_PORT}:${POSTGRES_PORT}

6
example.env Normal file
View File

@ -0,0 +1,6 @@
POSTGRES_DB=server-db
POSTGRES_USER=axum-user
POSTGRES_PASSWORD=my-cool-pass
POSTGRES_PORT=5432
POSTGRES_HOST=localhost
DATABASE_URL=postgres://axum-user:my-cool-pass@localhost:5432/server-db

View File

@ -2,10 +2,10 @@ use axum::{
Json,
extract::{Query, State},
response::IntoResponse,
routing::{delete, get, post},
routing::{get, post},
};
use sqlx::PgPool;
use std::fs;
use std::{env, fs};
use tokio::net::TcpListener;
#[derive(Clone)]
@ -51,7 +51,17 @@ pub struct GetGameQuery {
fn database_url() -> String {
let _ = dotenvy::dotenv();
let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL should be set");
let database_url = format!(
"postgres://{}:{}@{}:{}/{}",
env::var("POSTGRES_USER").unwrap(),
env::var("POSTGRES_PASSWORD").unwrap(),
env::var("POSTGRES_HOST").unwrap(),
env::var("POSTGRES_PORT").unwrap(),
env::var("POSTGRES_DB").unwrap(),
);
if database_url != env::var("DATABASE_URL").unwrap() {
panic!("DATABASE_URL is not set correctly");
}
println!("DATABASE_URL={database_url}");
database_url
}
@ -68,7 +78,7 @@ async fn create_table(pool: &PgPool) {
fn router(state: AppState) -> axum::Router {
axum::Router::new()
.route("/api/games", get(games_list).post(add_game))
.route("/api/games", get(games_list).post(insert_game))
.route("/api/games/{id}", post(insert_game).delete(delete_game))
.with_state(state)
}
@ -89,10 +99,7 @@ async fn main() {
axum::serve(listener, router(state)).await.unwrap();
}
async fn games_list(
State(state): State<AppState>,
Query(query): Query<GetGameQuery>,
) -> impl IntoResponse {
async fn games_list(State(state): State<AppState>) -> impl IntoResponse {
let games: Vec<Game> = sqlx::query_as!(Game, "SELECT * FROM games")
.fetch_all(&state.pool)
.await
@ -101,63 +108,40 @@ async fn games_list(
Json(games)
}
async fn add_game(
State(state): State<AppState>,
Json(game): Json<CreateGame>,
) -> impl IntoResponse {
let result = sqlx::query!(
"INSERT INTO games (name, publishing_house, developer, description, multiplayer, is_free_to_play)
VALUES ($1, $2, $3, $4, $5, $6)",
game.name,
game.publishing_house,
game.developer,
game.description,
game.multiplayer,
game.is_free_to_play,
)
.execute(&state.pool)
.await;
match result {
Ok(_) => axum::http::StatusCode::CREATED,
Err(_) => axum::http::StatusCode::INTERNAL_SERVER_ERROR,
}
}
async fn insert_game(
State(state): State<AppState>,
Query(query): Query<GetGameQuery>,
Json(game): Json<CreateGame>,
) -> impl IntoResponse {
sqlx::query!(
"INSERT INTO games(name, publishing_house, developer, description, multiplayer, is_free_to_play) VALUES ($1, $2, $3, $4, $5, $6)",
game.name,
game.publishing_house,
game.developer,
game.description,
game.multiplayer,
game.is_free_to_play,
)
.execute(&state.pool)
.await
.unwrap();
let sql_up = if query.id.is_some() {
"UPDATE games SET name=$1, publishing_house=$2, developer=$3, description=$4, multiplayer=$5, is_free_to_play=$6 WHERE id=$7"
} else {
"INSERT INTO games(name, publishing_house, developer, description, multiplayer, is_free_to_play) VALUES ($1, $2, $3, $4, $5, $6)"
};
let mut sql_query = sqlx::query(sql_up)
.bind(game.name)
.bind(game.publishing_house)
.bind(game.developer)
.bind(game.description)
.bind(game.multiplayer)
.bind(game.is_free_to_play);
if let Some(id) = query.id {
sql_query = sql_query.bind(id);
}
sql_query.execute(&state.pool).await.unwrap();
axum::http::StatusCode::CREATED
}
use axum::extract::Path;
async fn delete_game(State(state): State<AppState>, Path(id): Path<i32>) -> impl IntoResponse {
sqlx::query!("DELETE FROM games WHERE id = $1", id)
.execute(&state.pool)
.await
.unwrap();
axum::http::StatusCode::OK
}
async fn delete_game(
State(state): State<AppState>,
Query(query): Query<GetGameQuery>,
) -> impl IntoResponse {
if let Some(id) = query.id {
let result = sqlx::query!("DELETE FROM games WHERE id = $1", id)
.execute(&state.pool)
.await;
match result {
Ok(_) => axum::http::StatusCode::OK,
Err(_) => axum::http::StatusCode::INTERNAL_SERVER_ERROR,
}
} else {
axum::http::StatusCode::BAD_REQUEST
}
}