diff --git a/src/main.rs b/src/main.rs index 2119049..5d7ff56 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,6 @@ use tower_http::trace::TraceLayer; use tracing::Level; use crate::routing::routes::*; -use crate::routing::routes::index::not_found; mod expressions; mod parsing; @@ -27,19 +26,18 @@ async fn main() { .compact() .init(); - let routes = simplify::router() - .merge(table::router()) - .merge(index::router()) - .fallback(not_found); + let routes = join_routes![ + simplify::router(), + index::router(), + table::router() + ].fallback(index::not_found); - let app = routes - .layer(CorsLayer::new().allow_origin(Any)) - .layer(TraceLayer::new_for_http() - .make_span_with(trace::DefaultMakeSpan::new() - .level(Level::INFO)) - .on_response(trace::DefaultOnResponse::new() - .level(Level::INFO)) - ); + let app = create_app!(routes, + CorsLayer::new().allow_origin(Any), + TraceLayer::new_for_http() + .make_span_with(trace::DefaultMakeSpan::new().level(Level::INFO)) + .on_response(trace::DefaultOnResponse::new().level(Level::INFO)) + ); tracing::info!("Starting server on: {addr}"); diff --git a/src/routing/response.rs b/src/routing/response.rs index c7b8a20..e9b4461 100644 --- a/src/routing/response.rs +++ b/src/routing/response.rs @@ -59,8 +59,17 @@ pub struct SimplifyResponse { #[derive(Serialize, IntoResponse)] #[serde(rename_all = "camelCase")] -pub struct IsLegalResponse { - pub is_legal: bool, +pub(crate) struct IsValidResponse { + pub is_valid: bool, +} + +impl IsValidResponse { + pub const fn valid() -> Self { + Self { is_valid: true } + } + pub const fn invalid() -> Self { + Self { is_valid: false } + } } #[derive(Serialize, IntoResponse)] diff --git a/src/routing/routes/index.rs b/src/routing/routes/index.rs index 093c49d..1313cfd 100644 --- a/src/routing/routes/index.rs +++ b/src/routing/routes/index.rs @@ -1,11 +1,13 @@ use axum::extract::Path; use axum::http::StatusCode; +use axum::Json; use axum::response::{IntoResponse, Response}; +use serde::Serialize; use crate::{load_html, router}; use crate::expressions::expression::Expression; use crate::routing::error::{Error, ErrorKind}; -use crate::routing::response::IsLegalResponse; +use crate::routing::response::IsValidResponse; router!( get "/" => index, @@ -13,21 +15,34 @@ router!( get "/is-valid/:exp" => is_valid ); -async fn index() -> &'static str { - "Welcome to the Simplify Truths API!\n" +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct Info { + message: &'static str, + docs: &'static str, + created_by: String, } -async fn open_api() -> Response { - load_html!("openapi.html").into_response() +async fn index() -> Json { + let author = env!("CARGO_PKG_AUTHORS"); + Json(Info { + message: "Welcome to the Simplify Truths API!", + docs: "The API documentation can be found at /openapi", + created_by: format!("Created by: {}", author), + }) +} + +async fn open_api() -> impl IntoResponse { + load_html!("openapi.html") } async fn is_valid(Path(path): Path) -> Response { match Expression::try_from(path.as_str()) { - Ok(_) => IsLegalResponse { is_legal: true }.into_response(), + Ok(_) => IsValidResponse::valid().into_response(), Err(error) => Error::new(error.to_string(), ErrorKind::InvalidExpression).into_response() } } -pub(crate) async fn not_found() -> Response { - (StatusCode::NOT_FOUND, load_html!("not-found.html")).into_response() +pub(crate) async fn not_found() -> impl IntoResponse { + (StatusCode::NOT_FOUND, load_html!("not-found.html")) } diff --git a/src/utils/axum.rs b/src/utils/axum.rs index 812304e..599096e 100644 --- a/src/utils/axum.rs +++ b/src/utils/axum.rs @@ -48,6 +48,20 @@ macro_rules! routes { }; } +#[macro_export] +macro_rules! join_routes { + ($($route:expr),* $(,)?) => { + axum::Router::new()$(.merge($route))* + }; +} + +#[macro_export] +macro_rules! create_app { + ($router:expr, $($layer:expr),* $(,)?) => { + $router$(.layer($layer))* + }; +} + /// Load an HTML file from the given file path, relative to the resource directory. /// # Arguments /// * `file_path` - The path to the HTML file.