From 620ea11f360dcdeb7c2f6b2df7a3ee8f8b70a15f Mon Sep 17 00:00:00 2001 From: Zackary Troop Date: Tue, 6 Feb 2024 17:46:48 -0500 Subject: [PATCH] Add request method support --- examples/config.yml | 4 ++-- src/handlers.rs | 30 ++++++++++++++++++++++++++ src/macros.rs | 18 ++++++++++++++++ src/main.rs | 52 ++++++++++++++++----------------------------- src/structs.rs | 13 ++++++++++++ 5 files changed, 81 insertions(+), 36 deletions(-) create mode 100644 src/handlers.rs create mode 100644 src/macros.rs diff --git a/examples/config.yml b/examples/config.yml index 8c77b3c..4db13bf 100644 --- a/examples/config.yml +++ b/examples/config.yml @@ -1,5 +1,6 @@ - name: "Example Endpoint 1" endpoint: "/example1" + method: "POST" data: message: "This is the first example response." details: @@ -11,6 +12,7 @@ - name: "Example Endpoint 2" endpoint: "/example2" + method: "POST" data: success: true payload: @@ -20,6 +22,4 @@ - name: "Not Found Example" endpoint: "/notfound" - data: - error: "Resource not found." status: 404 \ No newline at end of file diff --git a/src/handlers.rs b/src/handlers.rs new file mode 100644 index 0000000..e8c915f --- /dev/null +++ b/src/handlers.rs @@ -0,0 +1,30 @@ +use axum::response::IntoResponse; +use axum::{http::StatusCode, response::Json}; +use serde_json::Value; +use std::collections::HashMap; +use std::str::FromStr; +use std::sync::Arc; + +// Default handler for no YAML configuration +pub async fn default_handler() -> &'static str { + "OK" +} + +// Handler for custom route +pub async fn handle_custom_route( + data: Arc, + status: StatusCode, + headers: Arc>, +) -> impl axum::response::IntoResponse { + let mut response = axum::response::Response::new(Json(data.as_ref().clone()).into_response()); + *response.status_mut() = status; + + for (key, value) in headers.as_ref() { + response.headers_mut().insert( + axum::http::header::HeaderName::from_str(key).unwrap(), + axum::http::header::HeaderValue::from_str(value).unwrap(), + ); + } + + response +} diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 0000000..f81f8da --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,18 @@ +#[macro_export] +macro_rules! route_with_method { + ($app:expr, $method:expr, $endpoint:expr, $handler:expr) => { + match $method { + $crate::structs::HttpMethod::Get => $app.route($endpoint, axum::routing::get($handler)), + $crate::structs::HttpMethod::Post => { + $app.route($endpoint, axum::routing::post($handler)) + } + $crate::structs::HttpMethod::Put => $app.route($endpoint, axum::routing::put($handler)), + $crate::structs::HttpMethod::Patch => { + $app.route($endpoint, axum::routing::patch($handler)) + } + $crate::structs::HttpMethod::Delete => { + $app.route($endpoint, axum::routing::delete($handler)) + } + } + }; +} diff --git a/src/main.rs b/src/main.rs index 80cdab8..e56a055 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,13 @@ -use axum::response::IntoResponse; -use axum::{http::StatusCode, response::Json, routing::get, Router}; +use axum::{http::StatusCode, Router}; use clap::Parser; use serde_json::Value; use std::collections::HashMap; -use std::str::FromStr; use std::sync::Arc; use tower_http::trace::{self, TraceLayer}; use tracing::Level; +mod handlers; +mod macros; mod structs; #[tokio::main] @@ -33,16 +33,24 @@ async fn main() { let route_headers = Arc::new(config.headers.unwrap_or(HashMap::::new())); let status_code = StatusCode::from_u16(config.status).unwrap_or(StatusCode::OK); - app = app.route( - &config.endpoint, - get(move || { - handle_custom_route(route_data.clone(), status_code, route_headers.clone()) - }), - ); + app = route_with_method!(app, config.method, &config.endpoint, move || { + handlers::handle_custom_route( + route_data.clone(), + status_code, + route_headers.clone(), + ) + }); } } else { // Default behavior - app = app.route("/", get(default_handler)); + app = app.route( + "/*path", + axum::routing::get(handlers::default_handler) + .post(handlers::default_handler) + .put(handlers::default_handler) + .patch(handlers::default_handler) + .delete(handlers::default_handler), + ); } // Add middleware @@ -65,27 +73,3 @@ fn load_yaml_config(file_path: &str) -> Vec { let file_content = std::fs::read_to_string(file_path).expect("Unable to read file"); serde_yaml::from_str(&file_content).expect("Unable to parse YAML") } - -// Default handler for no YAML configuration -async fn default_handler() -> &'static str { - "OK" -} - -// Handler for custom route -async fn handle_custom_route( - data: Arc, - status: StatusCode, - headers: Arc>, -) -> impl axum::response::IntoResponse { - let mut response = axum::response::Response::new(Json(data.as_ref().clone()).into_response()); - *response.status_mut() = status; - - for (key, value) in headers.as_ref() { - response.headers_mut().insert( - axum::http::header::HeaderName::from_str(key).unwrap(), - axum::http::header::HeaderValue::from_str(value).unwrap(), - ); - } - - response -} diff --git a/src/structs.rs b/src/structs.rs index d72daa0..a234715 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -15,7 +15,20 @@ pub struct Args { pub struct EndpointConfig { pub name: String, pub endpoint: String, + #[serde(default)] + pub method: HttpMethod, pub data: Option, pub status: u16, pub headers: Option>, } + +#[derive(Debug, Serialize, Deserialize, Default)] +#[serde(rename_all = "UPPERCASE")] +pub enum HttpMethod { + #[default] + Get, + Post, + Put, + Delete, + Patch, +}