trifid/trifid-api/src/main.rs

113 lines
3.8 KiB
Rust

use std::error::Error;
use std::fs;
use std::path::Path;
use dotenvy::dotenv;
use log::{error, info};
use rocket::{catchers, routes};
use sqlx::migrate::Migrator;
use sqlx::postgres::PgPoolOptions;
use crate::config::TFConfig;
pub mod format;
pub mod util;
pub mod db;
pub mod config;
pub mod routes;
static MIGRATOR: Migrator = sqlx::migrate!();
#[rocket::main]
async fn main() -> Result<(), Box<dyn Error>> {
let _ = rocket::build();
info!("[tfapi] loading config");
let _ = dotenv();
if std::env::var("CONFIG_FILE").is_err() && !Path::new("config.toml").exists() {
error!("[tfapi] fatal: the environment variable CONFIG_FILE is not set");
error!("[tfapi] help: try creating a .env file that sets it");
error!("[tfapi] help: or, create a file config.toml with your config, as it is loaded automatically");
std::process::exit(1);
}
let config_file;
if Path::new("config.toml").exists() {
config_file = "config.toml".to_string();
} else {
config_file = std::env::var("CONFIG_FILE").unwrap();
}
let config_data = match fs::read_to_string(&config_file) {
Ok(d) => d,
Err(e) => {
error!("[tfapi] fatal: unable to read config from {}", config_file);
error!("[tfapi] fatal: {}", e);
std::process::exit(1);
}
};
let config: TFConfig = match toml::from_str(&config_data) {
Ok(c) => c,
Err(e) => {
error!("[tfapi] fatal: unable to parse config from {}", config_file);
error!("[tfapi] fatal: {}", e);
std::process::exit(1);
}
};
info!("[tfapi] connecting to database pool");
let pool = match PgPoolOptions::new().max_connections(5).connect(&config.db_url).await {
Ok(p) => p,
Err(e) => {
error!("[tfapi] fatal: unable to connect to database pool");
error!("[tfapi] fatal: {}", e);
std::process::exit(1);
}
};
info!("[tfapi] running database migrations");
MIGRATOR.run(&pool).await?;
info!("[tfapi] building rocket config");
let figment = rocket::Config::figment().merge(("port", config.listen_port));
/*
error_handler!(400, "ERR_MALFORMED_REQUEST", "unable to parse the request body, is it properly formatted?");
error_handler!(401, "ERR_AUTHENTICATION_REQUIRED", "this endpoint requires authentication but it was not provided");
error_handler!(403, "ERR_UNAUTHORIZED", "authorization was provided but it is expired or invalid");
error_handler!(404, "ERR_NOT_FOUND", "resource not found");
error_handler!(405, "ERR_METHOD_NOT_ALLOWED", "method not allowed for this endpoint");
error_handler!(500, "ERR_QL_QUERY_FAILED", "graphql query timed out");
error_handler!(501, "ERR_NOT_IMPLEMENTED", "query not supported by this version of graphql");
error_handler!(502, "ERR_PROXY_ERR", "servers under load, please try again later");
error_handler!(503, "ERR_SERVER_OVERLOADED", "servers under load, please try again later");
error_handler!(504, "ERR_PROXY_TIMEOUT", "servers under load, please try again later");
error_handler!(505, "ERR_CLIENT_UNSUPPORTED", "your version of dnclient is out of date, please update");
*/
let _ = rocket::custom(figment)
.mount("/", routes![
crate::routes::v1::auth::verify_magic_link::verify_magic_link
])
.register("/", catchers![
crate::routes::handler_400,
crate::routes::handler_401,
crate::routes::handler_403,
crate::routes::handler_404,
crate::routes::handler_500,
crate::routes::handler_501,
crate::routes::handler_502,
crate::routes::handler_503,
crate::routes::handler_504,
crate::routes::handler_505,
])
.manage(pool)
.manage(config)
.launch().await?;
Ok(())
}