diff options
author | Santo Cariotti <santo@dcariotti.me> | 2024-09-16 22:40:24 +0200 |
---|---|---|
committer | Santo Cariotti <santo@dcariotti.me> | 2024-09-16 22:40:24 +0200 |
commit | 99bb59373b5918b2baf7e70f510d2b0ec1122a28 (patch) | |
tree | c44dc2572c520402812fab2c62bf9f96d1cf2628 | |
parent | ccde4a437999267ae1f62316bebcc09ea7dc027d (diff) |
Use `AppState` instead of `String` using some traits
-rw-r--r-- | src/db.rs | 2 | ||||
-rw-r--r-- | src/errors.rs | 30 | ||||
-rw-r--r-- | src/graphql/query.rs | 14 | ||||
-rw-r--r-- | src/graphql/types/alert.rs | 78 | ||||
-rw-r--r-- | src/graphql/types/jwt.rs | 5 | ||||
-rw-r--r-- | src/graphql/types/notification.rs | 32 | ||||
-rw-r--r-- | src/graphql/types/position.rs | 43 | ||||
-rw-r--r-- | src/graphql/types/user.rs | 42 | ||||
-rw-r--r-- | src/main.rs | 37 |
9 files changed, 151 insertions, 132 deletions
@@ -6,7 +6,7 @@ use tokio_postgres::{Client, NoTls}; pub async fn setup() -> Result<Client, AppError> { let database_url = &crate::config::CONFIG.database_url; - let (client, connection) = tokio_postgres::connect(database_url, NoTls).await.unwrap(); + let (client, connection) = tokio_postgres::connect(database_url, NoTls).await?; // Spawn a new task to run the connection to the database tokio::spawn(async move { diff --git a/src/errors.rs b/src/errors.rs index 1b9a802..3dda65c 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,3 +1,5 @@ +use core::fmt; + use axum::{ http::StatusCode, response::{IntoResponse, Response}, @@ -66,3 +68,31 @@ impl From<std::io::Error> for AppError { AppError::BadRequest(error.to_string()) } } + +/// Implementation of the `{}` marker for AppError +impl fmt::Display for AppError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + AppError::Database => write!(f, "Database"), + AppError::BadRequest(value) => write!(f, "BadRequest: {}", value), + AppError::NotFound(value) => write!(f, "Not found: {}", value), + AppError::TokenCreation => write!(f, "Token creation"), + AppError::InvalidToken => write!(f, "Invalid Token"), + AppError::Unauthorized => write!(f, "Unauthorized"), + } + } +} + +/// A tokio_postgres error is mapped to an `AppError::Database` +impl From<tokio_postgres::Error> for AppError { + fn from(_: tokio_postgres::Error) -> Self { + AppError::Database + } +} + +/// A async_graphql error is mapped to an `AppError::BadRequest` +impl From<async_graphql::Error> for AppError { + fn from(value: async_graphql::Error) -> Self { + AppError::BadRequest(value.message) + } +} diff --git a/src/graphql/query.rs b/src/graphql/query.rs index e3750c9..9e6e0c3 100644 --- a/src/graphql/query.rs +++ b/src/graphql/query.rs @@ -1,4 +1,4 @@ -use crate::graphql::types::*; +use crate::{errors::AppError, graphql::types::*}; use async_graphql::{Context, Object}; /// Query struct @@ -25,7 +25,7 @@ impl Query { ctx: &Context<'ctx>, #[graphql(desc = "Limit results")] limit: Option<i64>, #[graphql(desc = "Offset results")] offset: Option<i64>, - ) -> Result<Option<Vec<user::User>>, String> { + ) -> Result<Option<Vec<user::User>>, AppError> { user::query::get_users(ctx, limit, offset).await } @@ -42,7 +42,7 @@ impl Query { &self, ctx: &Context<'ctx>, #[graphql(desc = "User to find")] id: i32, - ) -> Result<user::User, String> { + ) -> Result<user::User, AppError> { user::query::get_user_by_id(ctx, id).await } @@ -61,7 +61,7 @@ impl Query { #[graphql(desc = "Filter by user id")] user_id: Option<i32>, #[graphql(desc = "Limit results")] limit: Option<i64>, #[graphql(desc = "Offset results")] offset: Option<i64>, - ) -> Result<Option<Vec<position::Position>>, String> { + ) -> Result<Option<Vec<position::Position>>, AppError> { position::query::get_positions(ctx, user_id, limit, offset).await } @@ -81,7 +81,7 @@ impl Query { #[graphql(desc = "Filter by moving activity")] moving_activity: Option< position::MovingActivity, >, - ) -> Result<Option<Vec<position::Position>>, String> { + ) -> Result<Option<Vec<position::Position>>, AppError> { position::query::last_positions(ctx, moving_activity).await } @@ -100,7 +100,7 @@ impl Query { #[graphql(desc = "Filter by ID")] id: Option<i32>, #[graphql(desc = "Limit results")] limit: Option<i64>, #[graphql(desc = "Offset results")] offset: Option<i64>, - ) -> Result<Option<Vec<alert::Alert>>, String> { + ) -> Result<Option<Vec<alert::Alert>>, AppError> { alert::query::get_alerts(ctx, id, limit, offset).await } @@ -128,7 +128,7 @@ impl Query { #[graphql(desc = "Filter by alert ID")] alert_id: Option<i32>, #[graphql(desc = "Limit results")] limit: Option<i64>, #[graphql(desc = "Offset results")] offset: Option<i64>, - ) -> Result<Option<Vec<notification::Notification>>, String> { + ) -> Result<Option<Vec<notification::Notification>>, AppError> { notification::query::get_notifications(ctx, seen, id, alert_id, limit, offset).await } } diff --git a/src/graphql/types/alert.rs b/src/graphql/types/alert.rs index 69e8f31..6d27626 100644 --- a/src/graphql/types/alert.rs +++ b/src/graphql/types/alert.rs @@ -1,4 +1,5 @@ use crate::{ + errors::AppError, expo, graphql::types::{ jwt::Authentication, @@ -61,17 +62,18 @@ pub mod query { // Optional offset results. It should be used with limit field. offset: Option<i64>, - ) -> Result<Option<Vec<Alert>>, String> { + ) -> Result<Option<Vec<Alert>>, AppError> { let state = ctx.data::<AppState>().expect("Can't connect to db"); let client = &*state.client; - let auth: &Authentication = ctx.data().unwrap(); + let auth: &Authentication = ctx.data()?; match auth { - Authentication::NotLogged => Err("Unauthorized".to_string()), + Authentication::NotLogged => Err(AppError::Unauthorized), Authentication::Logged(_) => { let rows = match id { - Some(id) => client - .query( - "SELECT id, + Some(id) => { + client + .query( + "SELECT id, user_id, extract(epoch from created_at)::double precision as created_at, ST_AsText(area) as area, @@ -83,13 +85,14 @@ pub mod query { reached_users FROM alerts WHERE id = $1", - &[&id], - ) - .await - .unwrap(), - None => client - .query( - "SELECT id, + &[&id], + ) + .await? + } + None => { + client + .query( + "SELECT id, user_id, extract(epoch from created_at)::double precision as created_at, ST_AsText(area) as area, @@ -103,10 +106,10 @@ pub mod query { ORDER BY id DESC LIMIT $1 OFFSET $2", - &[&limit.unwrap_or(20), &offset.unwrap_or(0)], - ) - .await - .unwrap(), + &[&limit.unwrap_or(20), &offset.unwrap_or(0)], + ) + .await? + } }; let alerts: Vec<Alert> = rows @@ -141,13 +144,13 @@ pub mod mutations { let state = ctx.data::<AppState>().expect("Can't connect to db"); let client = &*state.client; - let auth: &Authentication = ctx.data().unwrap(); + let auth: &Authentication = ctx.data()?; match auth { - Authentication::NotLogged => Err(async_graphql::Error::new("Can't find the owner")), + Authentication::NotLogged => Err(AppError::NotFound("Owner".to_string()).into()), Authentication::Logged(claims) => { - let claim_user = find_user(client, claims.user_id).await.unwrap(); + let claim_user = find_user(client, claims.user_id).await?; if !claim_user.is_admin { - return Err(async_graphql::Error::new("Unauthorized")); + return Err(AppError::Unauthorized.into()); } let points: String = input @@ -165,19 +168,16 @@ pub mod mutations { let polygon = format!("ST_MakePolygon(ST_MakeLine(ARRAY[{}]))", points); let valid_query = format!("SELECT ST_IsValid({}) as is_valid", polygon); - let rows; - match client.query(&valid_query, &[]).await { - Ok(r) => { - rows = r; - } + let rows = match client.query(&valid_query, &[]).await { + Ok(r) => r, Err(_) => { - return Err(async_graphql::Error::new("Polygon is not valid")); + return Err(AppError::BadRequest("Polygon is not valid".to_string()).into()); } }; let is_valid: bool = rows[0].get("is_valid"); if !is_valid { - return Err(async_graphql::Error::new("Polygon is not valid")); + return Err(AppError::BadRequest("Polygon is not valid".to_string()).into()); } let insert_query = format!( @@ -198,8 +198,7 @@ pub mod mutations { &insert_query, &[&claims.user_id, &input.text1, &input.text2, &input.text3], ) - .await - .unwrap(); + .await?; let mut alert = rows .iter() .map(|row| Alert { @@ -217,7 +216,7 @@ pub mod mutations { .collect::<Vec<Alert>>() .first() .cloned() - .ok_or_else(|| async_graphql::Error::new("Failed to create alert"))?; + .ok_or_else(|| AppError::BadRequest("Failed to create alert".to_string()))?; struct Level<'a> { text: &'a str, @@ -259,8 +258,7 @@ pub mod mutations { )", &[&alert.id, &level.distance], ) - .await - .unwrap() + .await? .iter() .map(|row| row.get(0)) .filter(|id| !positions.contains(id)) @@ -274,8 +272,7 @@ pub mod mutations { *id, LevelAlert::from_str(level.text).unwrap(), ) - .await - .unwrap(); + .await?; notification_ids.push(notification); } @@ -284,7 +281,7 @@ pub mod mutations { .map(|i| format!("${}", i)) .collect(); - if placeholders.len() > 0 { + if !placeholders.is_empty() { let query = format!( "SELECT DISTINCT u.notification_token FROM positions p JOIN users u ON u.id = p.user_id WHERE p.id IN ({}) AND notification_token IS NOT NULL", @@ -299,8 +296,7 @@ pub mod mutations { .map(|id| id as &(dyn tokio_postgres::types::ToSql + Sync)) .collect::<Vec<&(dyn tokio_postgres::types::ToSql + Sync)>>(), ) - .await - .unwrap() + .await? .iter() .map(|row| { format!("ExponentPushToken[{}]", row.get::<usize, String>(0)) @@ -317,8 +313,7 @@ pub mod mutations { _ => "Check it out in app!".to_string(), }, ) - .await - .unwrap(); + .await?; } positions.extend(position_ids); @@ -329,8 +324,7 @@ pub mod mutations { "UPDATE alerts SET reached_users = $1 WHERE id = $2", &[&alert.reached_users, &alert.id], ) - .await - .unwrap(); + .await?; if let Err(e) = audio::tts( alert.text1.clone(), diff --git a/src/graphql/types/jwt.rs b/src/graphql/types/jwt.rs index b2a09c3..af4dc72 100644 --- a/src/graphql/types/jwt.rs +++ b/src/graphql/types/jwt.rs @@ -139,14 +139,13 @@ pub mod mutations { "SELECT id FROM users WHERE email = $1 AND password = $2", &[&input.email, &password], ) - .await - .unwrap(); + .await?; let id: Vec<i32> = rows.iter().map(|row| row.get(0)).collect(); if id.len() == 1 { // Create a new claim using the found ID let claims = Claims::new(id[0]); - let token = claims.get_token().unwrap(); + let token = claims.get_token()?; Ok(AuthBody::new(token, id[0])) } else { Err(Error::new("Invalid email or password")) diff --git a/src/graphql/types/notification.rs b/src/graphql/types/notification.rs index 1ff7532..88860a7 100644 --- a/src/graphql/types/notification.rs +++ b/src/graphql/types/notification.rs @@ -139,12 +139,12 @@ pub mod query { // Optional offset results. It should be used with limit field. offset: Option<i64>, - ) -> Result<Option<Vec<Notification>>, String> { + ) -> Result<Option<Vec<Notification>>, AppError> { let state = ctx.data::<AppState>().expect("Can't connect to db"); let client = &*state.client; - let auth: &Authentication = ctx.data().unwrap(); + let auth: &Authentication = ctx.data()?; match auth { - Authentication::NotLogged => Err("Unauthorized".to_string()), + Authentication::NotLogged => Err(AppError::Unauthorized), Authentication::Logged(claims) => { let claim_user = find_user(client, claims.user_id) .await @@ -196,29 +196,25 @@ pub mod query { .query(&format!( "{base_query} AND n.alert_id = $1 ORDER BY n.id DESC LIMIT $2 OFFSET $3", ), &[&ida, &limit, &offset]) - .await - .unwrap(), + .await?, Some (ida) => client .query(&format!( "{base_query} AND p.user_id = $1 AND n.alert_id = $2 ORDER BY n.id DESC LIMIT $3 OFFSET $4", ), &[&claim_user.id, &ida, &limit, &offset]) - .await - .unwrap(), + .await?, None if claim_user.is_admin => client .query( &format!("{base_query} ORDER BY n.id DESC LIMIT $1 OFFSET $2"), &[&limit, &offset], ) - .await - .unwrap(), + .await?, None => client.query( &format!("{base_query} AND p.user_id = $1 ORDER BY n.id DESC LIMIT $2 OFFSET $3"), &[&claim_user.id, &limit, &offset], ) - .await - .unwrap(), + .await?, }; let notifications: Vec<Notification> = rows @@ -267,9 +263,9 @@ pub mod mutations { let state = ctx.data::<AppState>().expect("Can't connect to db"); let client = &*state.client; - let auth: &Authentication = ctx.data().unwrap(); + let auth: &Authentication = ctx.data()?; match auth { - Authentication::NotLogged => Err(async_graphql::Error::new("Can't find the owner")), + Authentication::NotLogged => Err(AppError::NotFound("Owner".to_string()).into()), Authentication::Logged(claims) => { let user = find_user(client, claims.user_id) .await @@ -303,8 +299,7 @@ pub mod mutations { WHERE n.id = $1 ", &[&input.id]) - .await - .unwrap() + .await? .iter() .map(|row| Notification { id: row.get("id"), @@ -335,10 +330,10 @@ pub mod mutations { .collect::<Vec<Notification>>() .first() .cloned() - .ok_or_else(|| async_graphql::Error::new("Failed to get notification"))?; + .ok_or_else(|| AppError::NotFound("Notification".to_string()))?; if notification.position.user_id != user.id { - return Err(async_graphql::Error::new("Not found")); + return Err(AppError::NotFound("Notification".to_string()).into()); } client @@ -346,8 +341,7 @@ pub mod mutations { "UPDATE notifications SET seen = $1 WHERE id = $2", &[&input.seen, &input.id], ) - .await - .unwrap(); + .await?; Ok(notification) } diff --git a/src/graphql/types/position.rs b/src/graphql/types/position.rs index 22030c5..cbd0148 100644 --- a/src/graphql/types/position.rs +++ b/src/graphql/types/position.rs @@ -1,11 +1,13 @@ -use crate::{graphql::types::jwt::Authentication, state::AppState}; +use crate::{ + errors::AppError, + graphql::types::{jwt::Authentication, user::find_user}, + state::AppState, +}; use async_graphql::{Context, Enum, FieldResult, InputObject, SimpleObject}; use serde::{Deserialize, Serialize}; use std::error::Error; use tokio_postgres::types::{to_sql_checked, FromSql, IsNull, ToSql, Type}; -use super::user::find_user; - #[derive(Enum, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)] /// Enumeration which refers to the kind of moving activity pub enum MovingActivity { @@ -96,14 +98,17 @@ pub mod query { // Optional offset results. It should be used with limit field. offset: Option<i64>, - ) -> Result<Option<Vec<Position>>, String> { + ) -> Result<Option<Vec<Position>>, AppError> { let state = ctx.data::<AppState>().expect("Can't connect to db"); let client = &*state.client; - let auth: &Authentication = ctx.data().unwrap(); + let auth: &Authentication = ctx.data()?; match auth { - Authentication::NotLogged => Err("Unauthorized".to_string()), + Authentication::NotLogged => Err(AppError::Unauthorized), Authentication::Logged(claims) => { let rows; + let limit = limit.unwrap_or(20); + let offset = offset.unwrap_or(0); + let claim_user = find_user(client, claims.user_id) .await .expect("Should not be here"); @@ -118,7 +123,7 @@ pub mod query { ORDER BY id DESC LIMIT $2 OFFSET $3", - &[&id, &limit.unwrap_or(20), &offset.unwrap_or(0)]).await.unwrap(); + &[&id, &limit, &offset]).await?; } None => { rows = client.query(" @@ -127,7 +132,7 @@ pub mod query { ORDER BY id DESC LIMIT $1 OFFSET $2", - &[&limit.unwrap_or(20), &offset.unwrap_or(0)]).await.unwrap(); + &[&limit, &offset]).await?; } } } else { @@ -138,7 +143,7 @@ pub mod query { ORDER BY id DESC LIMIT $2 OFFSET $3", - &[&claim_user.id, &limit.unwrap_or(20), &offset.unwrap_or(0)]).await.unwrap(); + &[&claim_user.id, &limit, &offset]).await?; } let positions: Vec<Position> = rows @@ -165,19 +170,19 @@ pub mod query { // Optional filter by moving activity moving_activity: Option<MovingActivity>, - ) -> Result<Option<Vec<Position>>, String> { + ) -> Result<Option<Vec<Position>>, AppError> { let state = ctx.data::<AppState>().expect("Can't connect to db"); let client = &*state.client; - let auth: &Authentication = ctx.data().unwrap(); + let auth: &Authentication = ctx.data()?; match auth { - Authentication::NotLogged => Err("Unauthorized".to_string()), + Authentication::NotLogged => Err(AppError::Unauthorized), Authentication::Logged(claims) => { let claim_user = find_user(client, claims.user_id) .await .expect("Should not be here"); if !claim_user.is_admin { - return Err("Unauthorized".to_string()); + return Err(AppError::Unauthorized); } let rows = client @@ -187,8 +192,7 @@ pub mod query { FROM positions ORDER BY user_id, created_at DESC", &[], ) - .await - .unwrap(); + .await?; let positions: Vec<Position> = match moving_activity { Some(activity) => rows @@ -233,9 +237,11 @@ pub mod mutations { let state = ctx.data::<AppState>().expect("Can't connect to db"); let client = &*state.client; - let auth: &Authentication = ctx.data().unwrap(); + let auth: &Authentication = ctx.data()?; match auth { - Authentication::NotLogged => Err(async_graphql::Error::new("Can't find the owner")), + Authentication::NotLogged => { + Err(AppError::NotFound("Can't find the owner".to_string()).into()) + } Authentication::Logged(claims) => { let rows = client .query( @@ -254,8 +260,7 @@ pub mod mutations { &input.moving_activity, ], ) - .await - .unwrap(); + .await?; let positions: Vec<Position> = rows .iter() diff --git a/src/graphql/types/user.rs b/src/graphql/types/user.rs index 44cc87c..3361f4a 100644 --- a/src/graphql/types/user.rs +++ b/src/graphql/types/user.rs @@ -107,19 +107,19 @@ pub mod query { limit: Option<i64>, // Optional offset results. It should be used with limit field. offset: Option<i64>, - ) -> Result<Option<Vec<User>>, String> { + ) -> Result<Option<Vec<User>>, AppError> { let state = ctx.data::<AppState>().expect("Can't connect to db"); let client = &*state.client; - let auth: &Authentication = ctx.data().unwrap(); + let auth: &Authentication = ctx.data()?; match auth { - Authentication::NotLogged => Err("Unauthorized".to_string()), + Authentication::NotLogged => Err(AppError::Unauthorized), Authentication::Logged(claims) => { let claim_user = find_user(client, claims.user_id) .await .expect("Should not be here"); if !claim_user.is_admin { - return Err("Unauthorized".to_string()); + return Err(AppError::Unauthorized); } let rows = client @@ -127,8 +127,7 @@ pub mod query { "SELECT id, email, name, address, is_admin FROM users LIMIT $1 OFFSET $2", &[&limit.unwrap_or(20), &offset.unwrap_or(0)], ) - .await - .unwrap(); + .await?; let users: Vec<User> = rows .iter() @@ -149,12 +148,12 @@ pub mod query { } /// Get users from the database - pub async fn get_user_by_id<'ctx>(ctx: &Context<'ctx>, id: i32) -> Result<User, String> { + pub async fn get_user_by_id<'ctx>(ctx: &Context<'ctx>, id: i32) -> Result<User, AppError> { let state = ctx.data::<AppState>().expect("Can't connect to db"); let client = &*state.client; - let auth: &Authentication = ctx.data().unwrap(); + let auth: &Authentication = ctx.data()?; match auth { - Authentication::NotLogged => Err("Unauthorized".to_string()), + Authentication::NotLogged => Err(AppError::Unauthorized), Authentication::Logged(claims) => { let claim_user = find_user(client, claims.user_id) .await @@ -168,10 +167,9 @@ pub mod query { WHERE id = $1", &[&id], ) - .await - .unwrap(); + .await?; } else if claims.user_id != id { - return Err("Unauthorized".to_string()); + return Err(AppError::Unauthorized); } else { rows = client .query( @@ -179,8 +177,7 @@ pub mod query { WHERE id = $1", &[&claims.user_id], ) - .await - .unwrap(); + .await?; } let users: Vec<User> = rows @@ -197,7 +194,7 @@ pub mod query { .collect(); if users.is_empty() { - return Err("Not found".to_string()); + return Err(AppError::NotFound("User".to_string())); } Ok(users[0].clone()) @@ -217,7 +214,7 @@ pub mod mutations { let state = ctx.data::<AppState>().expect("Can't connect to db"); let client = &*state.client; - let auth: &Authentication = ctx.data().unwrap(); + let auth: &Authentication = ctx.data()?; match auth { Authentication::NotLogged => Err(Error::new("Can't find the owner")), Authentication::Logged(claims) => { @@ -230,8 +227,7 @@ pub mod mutations { "UPDATE users SET notification_token = $1 WHERE id = $2", &[&input.token, &claims.user_id], ) - .await - .unwrap(); + .await?; Ok(user) } @@ -247,7 +243,7 @@ pub mod mutations { let state = ctx.data::<AppState>().expect("Can't connect to db"); let client = &*state.client; - let auth: &Authentication = ctx.data().unwrap(); + let auth: &Authentication = ctx.data()?; match auth { Authentication::NotLogged => Err(Error::new("Can't find the owner")), Authentication::Logged(claims) => { @@ -268,8 +264,7 @@ pub mod mutations { "UPDATE users SET email = $1, name = $2, address = $3 WHERE id = $4", &[&input.email, &input.name, &input.address, &id], ) - .await - .unwrap(); + .await?; let user = find_user(client, claims.user_id) .await @@ -288,7 +283,7 @@ pub mod mutations { let state = ctx.data::<AppState>().expect("Can't connect to db"); let client = &*state.client; - let auth: &Authentication = ctx.data().unwrap(); + let auth: &Authentication = ctx.data()?; match auth { Authentication::NotLogged => Err(Error::new("Can't find the owner")), Authentication::Logged(claims) => { @@ -310,8 +305,7 @@ pub mod mutations { "UPDATE users SET password = $1 WHERE id = $2", &[&password, &user.id], ) - .await - .unwrap(); + .await?; Ok(user) } diff --git a/src/main.rs b/src/main.rs index 940bb5c..96cdc61 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,6 +17,7 @@ use axum::{ routing::{get, post}, Extension, Router, }; +use errors::AppError; use tokio::net::TcpListener; use tower_http::{ classify::ServerErrorsFailureClass, @@ -28,10 +29,10 @@ use tower_http::{ use tracing::Span; /// Create the app: setup everything and returns a `Router` -async fn create_app() -> Router { +async fn create_app() -> Result<Router, AppError> { logger::setup(); expo::setup(CONFIG.expo_access_token.clone()); - let dbclient = db::setup().await.unwrap(); + let dbclient = db::setup().await?; let state = state::AppState { client: Arc::new(dbclient), @@ -45,7 +46,7 @@ async fn create_app() -> Router { .data(state.clone()) .finish(); - Router::new() + Ok(Router::new() .route("/assets/sounds/:id", get(audio::show_file)) .route( "/graphql", @@ -75,24 +76,26 @@ async fn create_app() -> Router { .allow_headers(vec![header::CONTENT_TYPE, header::AUTHORIZATION]) .allow_origin(Any), ) - .layer(Extension(state)) + .layer(Extension(state))) } #[tokio::main(flavor = "current_thread")] async fn main() { - let app = create_app().await; + if let Ok(app) = create_app().await { + let host = &CONFIG.allowed_host; - let host = &CONFIG.allowed_host; + let addr = match host.parse::<SocketAddr>() { + Ok(addr) => addr, + Err(e) => { + panic!("`{}` {}", host, e); + } + }; + tracing::info!("Listening on {}", addr); - let addr = match host.parse::<SocketAddr>() { - Ok(addr) => addr, - Err(e) => { - panic!("`{}` {}", host, e); - } - }; - tracing::info!("Listening on {}", addr); - - axum::serve(TcpListener::bind(&addr).await.unwrap(), app) - .await - .unwrap(); + axum::serve(TcpListener::bind(&addr).await.unwrap(), app) + .await + .unwrap(); + } else { + tracing::error!("Can't create an application!"); + } } |