Skip to main content

rumtk_web/utils/
matcher.rs

1/*
2 * rumtk attempts to implement HL7 and medical protocols for interoperability in medicine.
3 * This toolkit aims to be reliable, simple, performant, and standards compliant.
4 * Copyright (C) 2025  Luis M. Santos, M.D. <lsantos@medicalmasses.com>
5 * Copyright (C) 2025  Ethan Dixon
6 * Copyright (C) 2025  MedicalMasses L.L.C. <contact@medicalmasses.com>
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20 */
21use crate::components::app_shell::app_shell;
22use crate::components::div::div;
23use crate::utils::defaults::DEFAULT_ROBOT_TXT;
24use crate::utils::form_data::compile_form_data;
25use crate::utils::types::SharedAppState;
26use crate::utils::{HTMLResult, RUMString};
27use crate::{rumtk_web_get_api_endpoint, rumtk_web_get_component, rumtk_web_render_component, RUMWebData, RUMWebResponse, RouterForm};
28use axum::body::Body;
29use axum::http::Response;
30use axum::response::{Html, IntoResponse};
31use rumtk_core::strings::rumtk_format;
32
33pub async fn default_robots_matcher(
34    _path: Vec<RUMString>,
35    _params: RUMWebData,
36    _state: SharedAppState,
37) -> HTMLResult {
38    RUMWebResponse::into_get_response(DEFAULT_ROBOT_TXT).into_html_result()
39}
40
41pub async fn default_page_matcher(
42    path: Vec<RUMString>,
43    params: RUMWebData,
44    state: SharedAppState,
45) -> HTMLResult {
46    let path_components = match path.first() {
47        Some(x) => x.split('/').collect::<Vec<&str>>(),
48        None => Vec::new(),
49    };
50
51    // Do not minify the page. we saved 0.3KB but transfer went from 5ms to 45ms
52    app_shell(&path_components, &params, state)
53}
54
55pub async fn default_api_matcher(
56    path: RUMString,
57    params: RUMWebData,
58    mut form: RouterForm,
59    state: SharedAppState,
60) -> HTMLResult {
61    let form_data = compile_form_data(&mut form).await?;
62    let api_endpoint = match rumtk_web_get_api_endpoint!(&path) {
63        Some(endpoint) => endpoint,
64        None => return Err(rumtk_format!("Requested endpoint is not registered!"))
65    };
66    api_endpoint(path, params, form_data, state)
67}
68
69pub async fn default_component_matcher(
70    path: Vec<RUMString>,
71    params: RUMWebData,
72    state: SharedAppState,
73) -> HTMLResult {
74    let path_components = match path.first() {
75        Some(x) => x.split('/').collect::<Vec<&str>>(),
76        None => Vec::new(),
77    };
78
79    let component = match path_components.last() {
80        Some(component) => component,
81        None => return Err(RUMString::from("Missing component name to fetch!")),
82    };
83
84    rumtk_web_render_component!(component, &[""], params, state)
85}
86
87pub fn match_maker(match_response: HTMLResult) -> Response<Body> {
88    match match_response {
89        Ok(res) => res.into_response(),
90        Err(e) => Html(String::default()).into_response(),
91    }
92}
93
94#[macro_export]
95macro_rules! rumtk_web_fetch {
96    ( $matcher:expr ) => {{
97        use axum::extract::{Path, Query, State};
98        use axum::response::{Html, Response};
99        use $crate::matcher::match_maker;
100        use $crate::utils::types::{RouterAppState, RouterComponents, RouterForm, RouterParams};
101
102        async |Path(path_params): RouterComponents,
103               Query(params): RouterParams,
104               State(state): RouterAppState|
105               -> Response {
106            let r = $matcher(path_params, params, state).await;
107            match_maker(r)
108        }
109    }};
110}
111
112#[macro_export]
113macro_rules! rumtk_web_api_process {
114    ( $matcher:expr ) => {{
115        use axum::extract::{Multipart, Path, Query, State};
116        use axum::response::{Html, Response};
117        use $crate::matcher::match_maker;
118        use $crate::utils::types::{RouterAPIPath, RouterAppState, RouterForm, RouterParams};
119
120        async |Path(path_params): RouterAPIPath,
121               Query(params): RouterParams,
122               State(state): RouterAppState,
123               mut form: RouterForm|
124               -> Response {
125            let r = $matcher(path_params, params, form, state).await;
126            match_maker(r)
127        }
128    }};
129}