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"
|
||||
|
||||
[dependencies]
|
||||
actix = "0.13"
|
||||
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("/")]
|
||||
async fn hello() -> impl Responder {
|
||||
HttpResponse::Ok().body("Hello world!")
|
||||
type Error = Box<dyn std::error::Error>;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Data {
|
||||
pub config: Config,
|
||||
pub start_time: SystemTime,
|
||||
}
|
||||
|
||||
#[post("/echo")]
|
||||
async fn echo(req_body: String) -> impl Responder {
|
||||
HttpResponse::Ok().body(req_body)
|
||||
}
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Error> {
|
||||
let config = ConfigBuilder::load().await?.build();
|
||||
|
||||
async fn manual_hello() -> impl Responder {
|
||||
HttpResponse::Ok().body("Hey there!")
|
||||
}
|
||||
let web = config.web.clone();
|
||||
|
||||
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()
|
||||
.service(hello)
|
||||
.service(echo)
|
||||
.route("/hey", web::get().to(manual_hello))
|
||||
.app_data(web::Data::new(data))
|
||||
.service(api::versions::res)
|
||||
.service(api::v1::web())
|
||||
})
|
||||
.bind(("127.0.0.1", 8080))?
|
||||
.bind((web.url, web.port))?
|
||||
.run()
|
||||
.await
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue