feat(dev) engines: "Dynamic Routing"
This commit is contained in:
parent
55270c0637
commit
6755e61163
3 changed files with 62 additions and 13 deletions
|
|
@ -5,4 +5,4 @@ CREATE TABLE secret_engines (
|
|||
engine_type TEXT NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO secret_engines (mount_point, engine_type) VALUES ('/kv-v2', 'kv');
|
||||
INSERT INTO secret_engines (mount_point, engine_type) VALUES ('/kv-v2', 'kv_v2');
|
||||
|
|
|
|||
|
|
@ -3,30 +3,76 @@ pub mod kv;
|
|||
use axum::{
|
||||
body::Body,
|
||||
extract::{Request, State},
|
||||
http::Uri,
|
||||
response::Response,
|
||||
http::{StatusCode, Uri},
|
||||
response::{IntoResponse, Response},
|
||||
Router,
|
||||
};
|
||||
use log::*;
|
||||
use tower::Service;
|
||||
|
||||
use crate::storage::DatabaseDriver;
|
||||
|
||||
#[derive(Clone)]
|
||||
/// State to be used to store the database pool
|
||||
/// and the routers for each engine
|
||||
struct EngineMapperState {
|
||||
pool: DatabaseDriver,
|
||||
kv_v2: Router<String>,
|
||||
}
|
||||
|
||||
/// Secret engine router
|
||||
pub fn secrets_router(pool: DatabaseDriver) -> Router<DatabaseDriver> {
|
||||
Router::new().fallback(engine_handler).with_state(pool)
|
||||
// State containing the pool and engine routers
|
||||
let state = EngineMapperState {
|
||||
pool: pool.clone(),
|
||||
kv_v2: kv::kv_router(pool.clone()),
|
||||
};
|
||||
|
||||
Router::new().fallback(engine_handler).with_state(state)
|
||||
}
|
||||
|
||||
async fn engine_handler(State(pool): State<DatabaseDriver>, req: Request) -> Response<Body> {
|
||||
match map_mount_points(req.uri(), &pool).await {
|
||||
Some((mount_path, engine_type)) => {
|
||||
info!("Found mount point {} of type {}", mount_path, engine_type);
|
||||
todo!()
|
||||
/// Map the request to the appropriate engine and call the router
|
||||
async fn engine_handler(
|
||||
// State(pool): State<DatabaseDriver>,
|
||||
State(engines): State<EngineMapperState>,
|
||||
req: Request,
|
||||
) -> Response<Body> {
|
||||
if let Some((mount_path, engine_type)) = map_mount_points(req.uri(), &engines.pool).await {
|
||||
info!("Found mount point {} of type {}", mount_path, engine_type);
|
||||
// Match the engine type to the appropriate router
|
||||
match engine_type.as_str() {
|
||||
"kv_v2" => call_router(engines.kv_v2, mount_path, req).await,
|
||||
// Mount point exists but the type is unknown
|
||||
_ => unknown_engine(engine_type).into_response(),
|
||||
}
|
||||
None => todo!(),
|
||||
} else {
|
||||
// Otherwise, the mount path could not be found
|
||||
(StatusCode::NOT_FOUND, "Mount path not found").into_response()
|
||||
}
|
||||
|
||||
// Response::new(Body::from("Mount path:"))
|
||||
}
|
||||
|
||||
/// Helper function to call the appropriate router with the request
|
||||
async fn call_router(engine: Router<String>, mount_path: String, req: Request) -> Response {
|
||||
engine
|
||||
.with_state(mount_path)
|
||||
.call(req)
|
||||
.await
|
||||
.into_response()
|
||||
}
|
||||
|
||||
/// HTTP error response for unknown engine types
|
||||
/// Occurs when the mount path is found in the database
|
||||
/// but the registered is unknown
|
||||
fn unknown_engine(engine_type: String) -> (StatusCode, String) {
|
||||
error!("Engine type {} not implemented", engine_type);
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
format!("Engine type {} not implemented", engine_type),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the mount path and engine type for the request,
|
||||
/// if the mount path is registed at the database
|
||||
async fn map_mount_points(req: &Uri, pool: &DatabaseDriver) -> Option<(String, String)> {
|
||||
let mut mount_path_fragments: Vec<&str> = req.path().split('/').collect();
|
||||
|
||||
|
|
@ -40,6 +86,7 @@ async fn map_mount_points(req: &Uri, pool: &DatabaseDriver) -> Option<(String, S
|
|||
.fetch_optional(pool)
|
||||
.await;
|
||||
|
||||
// Path found
|
||||
if let Ok(Some(row)) = record {
|
||||
trace!(
|
||||
"Mount path {} found with {:?} engine for route request: {}",
|
||||
|
|
@ -50,8 +97,10 @@ async fn map_mount_points(req: &Uri, pool: &DatabaseDriver) -> Option<(String, S
|
|||
|
||||
return Some((mount_path_fragments.join("/"), row.engine_type));
|
||||
} else {
|
||||
// Shorten the mount path to find a shorter match
|
||||
mount_path_fragments.pop();
|
||||
}
|
||||
}
|
||||
// If no mount path is found, return None
|
||||
None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use crate::engines::kv::structs::KvSecret;
|
|||
use crate::{engines::kv::logic::body_to_json, storage::DatabaseDriver};
|
||||
use axum::{extract::Path, routing::*, Router};
|
||||
|
||||
pub fn kv_router(pool: DatabaseDriver) -> Router<DatabaseDriver> {
|
||||
pub fn kv_router(pool: DatabaseDriver) -> Router<String> {
|
||||
Router::new()
|
||||
.route("/:mount_path/config", get(get_config))
|
||||
.route("/:mount_path/config", post(post_config))
|
||||
|
|
|
|||
Loading…
Reference in a new issue