Create initial api

This commit is contained in:
Radical 2025-04-28 23:20:37 +02:00
parent 1fa926dd05
commit f090fbafe7
7 changed files with 169 additions and 21 deletions

View file

@ -4,6 +4,12 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
actix = "0.13"
actix-web = "4.10" actix-web = "4.10"
#tokio = { version = "1.44", features = ["full"] } maybe serde = { version = "1.0.219", features = ["derive"] }
sqlx = "0.8"
toml = "0.8.21"
url = { version = "2.5.4", features = ["serde"] }
[dependencies.tokio]
version = "1.44"
features = ["full"]

2
src/api/mod.rs Normal file
View file

@ -0,0 +1,2 @@
pub mod v1;
pub mod versions;

8
src/api/v1/mod.rs Normal file
View file

@ -0,0 +1,8 @@
use actix_web::{web, Scope};
mod stats;
pub fn web() -> Scope {
web::scope("/v1")
.service(stats::res)
}

28
src/api/v1/stats.rs Normal file
View file

@ -0,0 +1,28 @@
use std::time::SystemTime;
use actix_web::{get, web, HttpResponse, Responder};
use serde::Serialize;
use crate::Data;
const VERSION: Option<&'static str> = option_env!("CARGO_PKG_VERSION");
#[derive(Serialize)]
struct Response {
accounts: usize,
uptime: u64,
version: String,
build_number: String,
}
#[get("/stats")]
pub async fn res(data: web::Data<Data>) -> impl Responder {
let response = Response {
accounts: 0,
uptime: SystemTime::now().duration_since(data.start_time).expect("Seriously why dont you have time??").as_secs(),
version: String::from(VERSION.unwrap_or_else(|| "UNKNOWN")),
build_number: String::from("how do i implement this?"),
};
HttpResponse::Ok().json(response)
}

23
src/api/versions.rs Normal file
View file

@ -0,0 +1,23 @@
use actix_web::{get, HttpResponse, Responder};
use serde::Serialize;
#[derive(Serialize)]
struct Response {
unstable_features: UnstableFeatures,
versions: Vec<String>,
}
#[derive(Serialize)]
struct UnstableFeatures;
#[get("/versions")]
pub async fn res() -> impl Responder {
let response = Response {
unstable_features: UnstableFeatures,
versions: vec![
String::from("1"),
]
};
HttpResponse::Ok().json(response)
}

71
src/config.rs Normal file
View file

@ -0,0 +1,71 @@
use serde::Deserialize;
use tokio::fs::read_to_string;
use crate::Error;
use url::Url;
#[derive(Debug, Deserialize)]
pub struct ConfigBuilder {
database: Database,
web: Option<WebBuilder>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct Database {
username: String,
password: String,
hostname: String,
port: u16
}
#[derive(Debug, Deserialize)]
struct WebBuilder {
url: Option<String>,
port: Option<u16>,
ssl: Option<bool>,
}
impl ConfigBuilder {
pub async fn load() -> Result<Self, Error> {
let raw = read_to_string("./config.toml").await?;
let config = toml::from_str(&raw)?;
Ok(config)
}
pub fn build(self) -> Config {
let web = if let Some(web) = self.web {
Web {
url: web.url.unwrap_or(String::from("0.0.0.0")),
port: web.port.unwrap_or(8080),
ssl: web.ssl.unwrap_or_default()
}
} else {
Web {
url: String::from("0.0.0.0"),
port: 8080,
ssl: false
}
};
Config {
database: self.database,
web,
}
}
}
#[derive(Debug, Clone)]
pub struct Config {
pub database: Database,
pub web: Web,
}
#[derive(Debug, Clone)]
pub struct Web {
pub url: String,
pub port: u16,
pub ssl: bool,
}

View file

@ -1,28 +1,38 @@
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder}; use std::time::SystemTime;
use actix_web::{web, App, HttpServer};
mod config;
use config::{Config, ConfigBuilder};
mod api;
#[get("/")] type Error = Box<dyn std::error::Error>;
async fn hello() -> impl Responder {
HttpResponse::Ok().body("Hello world!") #[derive(Clone)]
struct Data {
pub config: Config,
pub start_time: SystemTime,
} }
#[post("/echo")] #[tokio::main]
async fn echo(req_body: String) -> impl Responder { async fn main() -> Result<(), Error> {
HttpResponse::Ok().body(req_body) let config = ConfigBuilder::load().await?.build();
}
async fn manual_hello() -> impl Responder { let web = config.web.clone();
HttpResponse::Ok().body("Hey there!")
} let data = Data {
config,
start_time: SystemTime::now(),
};
HttpServer::new(move || {
let data = data.clone();
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new() App::new()
.service(hello) .app_data(web::Data::new(data))
.service(echo) .service(api::versions::res)
.route("/hey", web::get().to(manual_hello)) .service(api::v1::web())
}) })
.bind(("127.0.0.1", 8080))? .bind((web.url, web.port))?
.run() .run()
.await .await?;
Ok(())
} }