From c92515cecc89c4f0ea1bd1d13662b7c8152cd75a Mon Sep 17 00:00:00 2001 From: mbecker20 Date: Mon, 1 Jul 2024 01:44:07 -0700 Subject: [PATCH] combine into router --- bin/periphery/src/guard.rs | 69 ------------------- bin/periphery/src/handler.rs | 53 --------------- bin/periphery/src/main.rs | 16 ++--- bin/periphery/src/router.rs | 125 +++++++++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 133 deletions(-) delete mode 100644 bin/periphery/src/guard.rs delete mode 100644 bin/periphery/src/handler.rs create mode 100644 bin/periphery/src/router.rs diff --git a/bin/periphery/src/guard.rs b/bin/periphery/src/guard.rs deleted file mode 100644 index eb084af47..000000000 --- a/bin/periphery/src/guard.rs +++ /dev/null @@ -1,69 +0,0 @@ -use std::net::SocketAddr; - -use anyhow::{anyhow, Context}; -use axum::{ - body::Body, - extract::ConnectInfo, - http::{Request, StatusCode}, - middleware::Next, - response::Response, -}; -use serror::{AddStatusCode, AddStatusCodeError}; - -use crate::config::periphery_config; - -#[instrument(level = "debug")] -pub async fn guard_request_by_passkey( - req: Request, - next: Next, -) -> serror::Result { - if periphery_config().passkeys.is_empty() { - return Ok(next.run(req).await); - } - let Some(req_passkey) = req.headers().get("authorization") else { - return Err( - anyhow!("request was not sent with passkey") - .status_code(StatusCode::UNAUTHORIZED), - ); - }; - let req_passkey = req_passkey - .to_str() - .context("failed to convert passkey to str") - .status_code(StatusCode::UNAUTHORIZED)?; - if periphery_config() - .passkeys - .iter() - .any(|passkey| passkey == req_passkey) - { - Ok(next.run(req).await) - } else { - Err( - anyhow!("request passkey invalid") - .status_code(StatusCode::UNAUTHORIZED), - ) - } -} - -#[instrument(level = "debug")] -pub async fn guard_request_by_ip( - req: Request, - next: Next, -) -> serror::Result { - if periphery_config().allowed_ips.is_empty() { - return Ok(next.run(req).await); - } - let ConnectInfo(socket_addr) = req - .extensions() - .get::>() - .context("could not get ConnectionInfo of request") - .status_code(StatusCode::UNAUTHORIZED)?; - let ip = socket_addr.ip(); - if periphery_config().allowed_ips.contains(&ip) { - Ok(next.run(req).await) - } else { - Err( - anyhow!("requesting ip {ip} not allowed") - .status_code(StatusCode::UNAUTHORIZED), - ) - } -} diff --git a/bin/periphery/src/handler.rs b/bin/periphery/src/handler.rs deleted file mode 100644 index 5605e8c81..000000000 --- a/bin/periphery/src/handler.rs +++ /dev/null @@ -1,53 +0,0 @@ -use std::time::Instant; - -use anyhow::{anyhow, Context}; -use axum_extra::{headers::ContentType, TypedHeader}; -use resolver_api::Resolver; -use serror::Json; -use uuid::Uuid; - -use crate::State; - -pub async fn handler( - Json(request): Json, -) -> serror::Result<(TypedHeader, String)> { - let req_id = Uuid::new_v4(); - - let res = tokio::spawn(task(req_id, request)) - .await - .context("task handler spawn error"); - - if let Err(e) = &res { - warn!("request {req_id} spawn error: {e:#}"); - } - - Ok((TypedHeader(ContentType::json()), res??)) -} - -#[instrument(name = "PeripheryHandler")] -async fn task( - req_id: Uuid, - request: crate::api::PeripheryRequest, -) -> anyhow::Result { - let timer = Instant::now(); - - let res = - State - .resolve_request(request, ()) - .await - .map_err(|e| match e { - resolver_api::Error::Serialization(e) => { - anyhow!("{e:?}").context("response serialization error") - } - resolver_api::Error::Inner(e) => e, - }); - - if let Err(e) = &res { - warn!("request {req_id} error: {e:#}"); - } - - let elapsed = timer.elapsed(); - debug!("request {req_id} | resolve time: {elapsed:?}"); - - res -} diff --git a/bin/periphery/src/main.rs b/bin/periphery/src/main.rs index 9855d65fd..7b66de15f 100644 --- a/bin/periphery/src/main.rs +++ b/bin/periphery/src/main.rs @@ -4,14 +4,12 @@ extern crate tracing; use std::{net::SocketAddr, str::FromStr}; use anyhow::Context; -use axum::{middleware, routing::post, Router}; mod api; mod config; mod docker; -mod guard; -mod handler; mod helpers; +mod router; mod stats; struct State; @@ -29,20 +27,16 @@ async fn app() -> anyhow::Result<()> { SocketAddr::from_str(&format!("0.0.0.0:{}", config.port)) .context("failed to parse socket addr")?; - let app = Router::new() - .route("/", post(handler::handler)) - .layer(middleware::from_fn(guard::guard_request_by_ip)) - .layer(middleware::from_fn(guard::guard_request_by_passkey)); - - info!("starting server on {}", socket_addr); - let listener = tokio::net::TcpListener::bind(&socket_addr) .await .context("failed to bind tcp listener")?; + info!("monitor core started on {}", socket_addr); + axum::serve( listener, - app.into_make_service_with_connect_info::(), + router::router() + .into_make_service_with_connect_info::(), ) .await?; diff --git a/bin/periphery/src/router.rs b/bin/periphery/src/router.rs new file mode 100644 index 000000000..b9922a644 --- /dev/null +++ b/bin/periphery/src/router.rs @@ -0,0 +1,125 @@ +use std::{net::SocketAddr, time::Instant}; + +use anyhow::{anyhow, Context}; +use axum::{ + body::Body, + extract::ConnectInfo, + http::{Request, StatusCode}, + middleware::{self, Next}, + response::Response, + routing::post, + Router, +}; +use axum_extra::{headers::ContentType, TypedHeader}; +use resolver_api::Resolver; +use serror::{AddStatusCode, AddStatusCodeError, Json}; +use uuid::Uuid; + +use crate::{config::periphery_config, State}; + +pub fn router() -> Router { + Router::new() + .route("/", post(handler)) + .layer(middleware::from_fn(guard_request_by_ip)) + .layer(middleware::from_fn(guard_request_by_passkey)) +} + +async fn handler( + Json(request): Json, +) -> serror::Result<(TypedHeader, String)> { + let req_id = Uuid::new_v4(); + + let res = tokio::spawn(task(req_id, request)) + .await + .context("task handler spawn error"); + + if let Err(e) = &res { + warn!("request {req_id} spawn error: {e:#}"); + } + + Ok((TypedHeader(ContentType::json()), res??)) +} + +#[instrument(name = "PeripheryHandler")] +async fn task( + req_id: Uuid, + request: crate::api::PeripheryRequest, +) -> anyhow::Result { + let timer = Instant::now(); + + let res = + State + .resolve_request(request, ()) + .await + .map_err(|e| match e { + resolver_api::Error::Serialization(e) => { + anyhow!("{e:?}").context("response serialization error") + } + resolver_api::Error::Inner(e) => e, + }); + + if let Err(e) = &res { + warn!("request {req_id} error: {e:#}"); + } + + let elapsed = timer.elapsed(); + debug!("request {req_id} | resolve time: {elapsed:?}"); + + res +} + +#[instrument(level = "debug")] +async fn guard_request_by_passkey( + req: Request, + next: Next, +) -> serror::Result { + if periphery_config().passkeys.is_empty() { + return Ok(next.run(req).await); + } + let Some(req_passkey) = req.headers().get("authorization") else { + return Err( + anyhow!("request was not sent with passkey") + .status_code(StatusCode::UNAUTHORIZED), + ); + }; + let req_passkey = req_passkey + .to_str() + .context("failed to convert passkey to str") + .status_code(StatusCode::UNAUTHORIZED)?; + if periphery_config() + .passkeys + .iter() + .any(|passkey| passkey == req_passkey) + { + Ok(next.run(req).await) + } else { + Err( + anyhow!("request passkey invalid") + .status_code(StatusCode::UNAUTHORIZED), + ) + } +} + +#[instrument(level = "debug")] +async fn guard_request_by_ip( + req: Request, + next: Next, +) -> serror::Result { + if periphery_config().allowed_ips.is_empty() { + return Ok(next.run(req).await); + } + let ConnectInfo(socket_addr) = req + .extensions() + .get::>() + .context("could not get ConnectionInfo of request") + .status_code(StatusCode::UNAUTHORIZED)?; + let ip = socket_addr.ip(); + if periphery_config().allowed_ips.contains(&ip) { + Ok(next.run(req).await) + } else { + Err( + anyhow!("requesting ip {ip} not allowed") + .status_code(StatusCode::UNAUTHORIZED), + ) + } +}