Create initial api
This commit is contained in:
parent
1fa926dd05
commit
f090fbafe7
7 changed files with 169 additions and 21 deletions
10
Cargo.toml
10
Cargo.toml
|
@ -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
2
src/api/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
pub mod v1;
|
||||||
|
pub mod versions;
|
8
src/api/v1/mod.rs
Normal file
8
src/api/v1/mod.rs
Normal 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
28
src/api/v1/stats.rs
Normal 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
23
src/api/versions.rs
Normal 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
71
src/config.rs
Normal 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,
|
||||||
|
}
|
48
src/main.rs
48
src/main.rs
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue