From a622358477f72a750e1a75413220541137c66ba5 Mon Sep 17 00:00:00 2001 From: Brett Beutell Date: Mon, 28 Aug 2023 17:32:36 +0200 Subject: [PATCH 01/12] Add .vscode to gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 020a75e..71e8d77 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ target # This directory is created by the prometheus process # Could be removed once we persist the data somewhere else data + +.vscode \ No newline at end of file From 938d9caf2b6364f7add800ee49a8d24c30c837e4 Mon Sep 17 00:00:00 2001 From: Brett Beutell Date: Mon, 28 Aug 2023 18:01:24 +0200 Subject: [PATCH 02/12] Add proxy command (only starts webserver) --- src/bin/am/commands.rs | 6 +++ src/bin/am/commands/proxy.rs | 72 ++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 src/bin/am/commands/proxy.rs diff --git a/src/bin/am/commands.rs b/src/bin/am/commands.rs index 67f09a0..53ad57e 100644 --- a/src/bin/am/commands.rs +++ b/src/bin/am/commands.rs @@ -6,6 +6,7 @@ use std::path::PathBuf; use tracing::info; mod explore; +mod proxy; mod init; pub mod start; pub mod system; @@ -46,6 +47,10 @@ pub enum SubCommands { #[clap(alias = "explorer")] Explore(explore::Arguments), + /// Use am as a proxy to another prometheus instance + #[clap(alias = "proxy")] + Proxy(proxy::CliArguments), + /// Create a new `am.toml` file interactively with sensible defaults Init(init::Arguments), @@ -65,6 +70,7 @@ pub async fn handle_command(app: Application, config: AmConfig, mp: MultiProgres SubCommands::Start(args) => start::handle_command(args, config, mp).await, SubCommands::System(args) => system::handle_command(args, mp).await, SubCommands::Explore(args) => explore::handle_command(args).await, + SubCommands::Proxy(args) => proxy::handle_command(args).await, SubCommands::Init(args) => init::handle_command(args).await, SubCommands::Discord => { const URL: &str = "https://discord.gg/kHtwcH8As9"; diff --git a/src/bin/am/commands/proxy.rs b/src/bin/am/commands/proxy.rs new file mode 100644 index 0000000..db8fa79 --- /dev/null +++ b/src/bin/am/commands/proxy.rs @@ -0,0 +1,72 @@ +use crate::server::start_web_server; +use anyhow::{bail, Context, Result}; +use clap::Parser; +use directories::ProjectDirs; +use std::net::SocketAddr; +use tokio::select; +use tokio::sync::watch; +use tracing::info; + +#[derive(Parser, Clone)] +pub struct CliArguments { + /// The listen address for the web server of am. + /// + /// This includes am's HTTP API, the explorer and the proxy to the Prometheus, Gateway, etc. + #[clap( + short, + long, + env, + default_value = "127.0.0.1:6789", + alias = "explorer-address" + )] + listen_address: SocketAddr, +} + +#[derive(Debug, Clone)] +struct Arguments { + listen_address: SocketAddr, +} + +impl Arguments { + fn new(args: CliArguments) -> Self { + Arguments { + listen_address: args.listen_address, + } + } +} + +pub async fn handle_command(args: CliArguments) -> Result<()> { + let args = Arguments::new(args); + + // First let's retrieve the directory for our application to store data in. + let project_dirs = + ProjectDirs::from("", "autometrics", "am").context("Unable to determine home directory")?; + let local_data = project_dirs.data_local_dir().to_owned(); + + // Make sure that the local data directory exists for our application. + std::fs::create_dir_all(&local_data) + .with_context(|| format!("Unable to create data directory: {:?}", local_data))?; + + let (tx, _) = watch::channel(None); + + // Start web server for hosting the explorer, am api and proxies to the enabled services. + let web_server_task = async move { start_web_server(&args.listen_address, false, tx).await }; + + select! { + biased; + + _ = tokio::signal::ctrl_c() => { + info!("SIGINT signal received, exiting..."); + Ok(()) + } + + Err(err) = web_server_task => { + bail!("Web server exited with an error: {err:?}"); + } + + else => { + Ok(()) + } + } +} + From ddce8e4b304f07debdfa98e89bed511a032ed3eb Mon Sep 17 00:00:00 2001 From: Brett Beutell Date: Mon, 28 Aug 2023 19:55:22 +0200 Subject: [PATCH 03/12] Add option to not add prometheus routes when starting web server --- src/bin/am/commands.rs | 3 +-- src/bin/am/commands/proxy.rs | 4 ++-- src/bin/am/commands/start.rs | 5 +++-- src/bin/am/server.rs | 16 ++++++++++++---- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/bin/am/commands.rs b/src/bin/am/commands.rs index 53ad57e..673a5dc 100644 --- a/src/bin/am/commands.rs +++ b/src/bin/am/commands.rs @@ -6,8 +6,8 @@ use std::path::PathBuf; use tracing::info; mod explore; -mod proxy; mod init; +mod proxy; pub mod start; pub mod system; pub mod update; @@ -48,7 +48,6 @@ pub enum SubCommands { Explore(explore::Arguments), /// Use am as a proxy to another prometheus instance - #[clap(alias = "proxy")] Proxy(proxy::CliArguments), /// Create a new `am.toml` file interactively with sensible defaults diff --git a/src/bin/am/commands/proxy.rs b/src/bin/am/commands/proxy.rs index db8fa79..739c91e 100644 --- a/src/bin/am/commands/proxy.rs +++ b/src/bin/am/commands/proxy.rs @@ -50,7 +50,8 @@ pub async fn handle_command(args: CliArguments) -> Result<()> { let (tx, _) = watch::channel(None); // Start web server for hosting the explorer, am api and proxies to the enabled services. - let web_server_task = async move { start_web_server(&args.listen_address, false, tx).await }; + let web_server_task = + async move { start_web_server(&args.listen_address, false, false, tx).await }; select! { biased; @@ -69,4 +70,3 @@ pub async fn handle_command(args: CliArguments) -> Result<()> { } } } - diff --git a/src/bin/am/commands/start.rs b/src/bin/am/commands/start.rs index 33b1b6e..6b735c9 100644 --- a/src/bin/am/commands/start.rs +++ b/src/bin/am/commands/start.rs @@ -261,8 +261,9 @@ pub async fn handle_command(args: CliArguments, config: AmConfig, mp: MultiProgr let (tx, rx) = watch::channel(None); // Start web server for hosting the explorer, am api and proxies to the enabled services. - let web_server_task = - async move { start_web_server(&args.listen_address, args.pushgateway_enabled, tx).await }; + let web_server_task = async move { + start_web_server(&args.listen_address, true, args.pushgateway_enabled, tx).await + }; // Start Prometheus server let prometheus_args = args.clone(); diff --git a/src/bin/am/server.rs b/src/bin/am/server.rs index a574e70..44ea649 100644 --- a/src/bin/am/server.rs +++ b/src/bin/am/server.rs @@ -14,6 +14,7 @@ mod util; pub(crate) async fn start_web_server( listen_address: &SocketAddr, + enable_prometheus: bool, enable_pushgateway: bool, tx: Sender>, ) -> Result<()> { @@ -32,9 +33,13 @@ pub(crate) async fn start_web_server( }), ) .route("/explorer/", get(explorer::handler)) - .route("/explorer/*path", get(explorer::handler)) - .route("/prometheus/*path", any(prometheus::handler)) - .route("/prometheus", any(prometheus::handler)); + .route("/explorer/*path", get(explorer::handler)); + + if enable_prometheus { + app = app + .route("/prometheus/*path", any(prometheus::handler)) + .route("/prometheus", any(prometheus::handler)); + } if enable_pushgateway { app = app @@ -52,7 +57,10 @@ pub(crate) async fn start_web_server( debug!("Web server listening on {}", server.local_addr()); info!("Explorer endpoint: http://{}", server.local_addr()); - info!("Prometheus endpoint: http://127.0.0.1:9090/prometheus"); + + if enable_prometheus { + info!("Prometheus endpoint: http://127.0.0.1:9090/prometheus"); + } if enable_pushgateway { info!("Pushgateway endpoint: http://127.0.0.1:9091/pushgateway"); From c32023cf8fd877399d26b4c65b7a8df37bf48cf4 Mon Sep 17 00:00:00 2001 From: Brett Beutell Date: Mon, 28 Aug 2023 22:09:48 +0200 Subject: [PATCH 04/12] Implement option to proxy requests to prometheus --- src/bin/am/commands/proxy.rs | 13 +++++++-- src/bin/am/commands/start.rs | 9 ++++++- src/bin/am/server.rs | 47 +++++++++++++++++++++++++++++++-- src/bin/am/server/prometheus.rs | 9 ++++++- 4 files changed, 72 insertions(+), 6 deletions(-) diff --git a/src/bin/am/commands/proxy.rs b/src/bin/am/commands/proxy.rs index 739c91e..032103c 100644 --- a/src/bin/am/commands/proxy.rs +++ b/src/bin/am/commands/proxy.rs @@ -6,6 +6,7 @@ use std::net::SocketAddr; use tokio::select; use tokio::sync::watch; use tracing::info; +use url::Url; #[derive(Parser, Clone)] pub struct CliArguments { @@ -20,17 +21,24 @@ pub struct CliArguments { alias = "explorer-address" )] listen_address: SocketAddr, + + /// The url to which we should proxy requests to `/prometheus` + /// + #[clap(long, env, alias = "prometheus-address")] + prometheus_url: Option, } #[derive(Debug, Clone)] struct Arguments { listen_address: SocketAddr, + prometheus_url: Option, } impl Arguments { fn new(args: CliArguments) -> Self { Arguments { listen_address: args.listen_address, + prometheus_url: args.prometheus_url, } } } @@ -50,8 +58,9 @@ pub async fn handle_command(args: CliArguments) -> Result<()> { let (tx, _) = watch::channel(None); // Start web server for hosting the explorer, am api and proxies to the enabled services. - let web_server_task = - async move { start_web_server(&args.listen_address, false, false, tx).await }; + let web_server_task = async move { + start_web_server(&args.listen_address, false, false, args.prometheus_url, tx).await + }; select! { biased; diff --git a/src/bin/am/commands/start.rs b/src/bin/am/commands/start.rs index 6b735c9..40d2cb3 100644 --- a/src/bin/am/commands/start.rs +++ b/src/bin/am/commands/start.rs @@ -262,7 +262,14 @@ pub async fn handle_command(args: CliArguments, config: AmConfig, mp: MultiProgr // Start web server for hosting the explorer, am api and proxies to the enabled services. let web_server_task = async move { - start_web_server(&args.listen_address, true, args.pushgateway_enabled, tx).await + start_web_server( + &args.listen_address, + true, + args.pushgateway_enabled, + None, + tx, + ) + .await }; // Start Prometheus server diff --git a/src/bin/am/server.rs b/src/bin/am/server.rs index 44ea649..975a5a5 100644 --- a/src/bin/am/server.rs +++ b/src/bin/am/server.rs @@ -4,8 +4,10 @@ use axum::response::Redirect; use axum::routing::{any, get}; use axum::{Router, Server}; use std::net::SocketAddr; +use std::sync::Arc; use tokio::sync::watch::Sender; use tracing::{debug, info}; +use url::Url; mod explorer; mod prometheus; @@ -16,8 +18,11 @@ pub(crate) async fn start_web_server( listen_address: &SocketAddr, enable_prometheus: bool, enable_pushgateway: bool, + prometheus_proxy_url: Option, tx: Sender>, ) -> Result<()> { + let is_proxying_prometheus = prometheus_proxy_url.is_some(); + let should_enable_prometheus = enable_prometheus && !is_proxying_prometheus; let mut app = Router::new() // Any calls to the root should be redirected to the explorer which is most likely what the user wants to use. .route("/", get(|| async { Redirect::temporary("/explorer/") })) @@ -35,12 +40,46 @@ pub(crate) async fn start_web_server( .route("/explorer/", get(explorer::handler)) .route("/explorer/*path", get(explorer::handler)); - if enable_prometheus { + if should_enable_prometheus { app = app .route("/prometheus/*path", any(prometheus::handler)) .route("/prometheus", any(prometheus::handler)); } + // NOTE - this will override local prometheus routes if specified + if is_proxying_prometheus { + let prometheus_upstream_base = Arc::new(prometheus_proxy_url.clone().unwrap()); + + let handler = move |mut req: http::Request| { + let upstream_base = prometheus_upstream_base.clone(); + let path_and_query = req + .uri() + .path_and_query() + .map(|pq| pq.as_str()) + .unwrap_or(""); + if let Some(stripped_path) = path_and_query.strip_prefix("/prometheus") { + // 2. Remove the `/prometheus` prefix. + let new_path_and_query = + http::uri::PathAndQuery::from_maybe_shared(stripped_path.to_string()) + .expect("Invalid path"); + + // 3. Create a new URI with the modified path. + let mut new_uri_parts = req.uri().clone().into_parts(); + new_uri_parts.path_and_query = Some(new_path_and_query); + + let new_uri = http::Uri::from_parts(new_uri_parts).expect("Invalid URI"); + + // 4. Replace the request's URI with the modified URI. + *req.uri_mut() = new_uri; + } + async move { prometheus::handler_with_url(req, &*upstream_base).await } + }; + + app = app + .route("/prometheus/*path", any(handler.clone())) + .route("/prometheus", any(handler)); + } + if enable_pushgateway { app = app .route("/metrics", any(pushgateway::metrics_proxy_handler)) @@ -58,10 +97,14 @@ pub(crate) async fn start_web_server( info!("Explorer endpoint: http://{}", server.local_addr()); - if enable_prometheus { + if should_enable_prometheus { info!("Prometheus endpoint: http://127.0.0.1:9090/prometheus"); } + if is_proxying_prometheus { + info!("Proxying to prometheus: {}", prometheus_proxy_url.unwrap()); + } + if enable_pushgateway { info!("Pushgateway endpoint: http://127.0.0.1:9091/pushgateway"); } diff --git a/src/bin/am/server/prometheus.rs b/src/bin/am/server/prometheus.rs index d919aa0..860c7b7 100644 --- a/src/bin/am/server/prometheus.rs +++ b/src/bin/am/server/prometheus.rs @@ -4,6 +4,13 @@ use axum::response::IntoResponse; use url::Url; pub(crate) async fn handler(req: http::Request) -> impl IntoResponse { - let upstream_base = Url::parse("http://localhost:9090").unwrap(); + let upstream_base = url::Url::parse("http://localhost:9090").unwrap(); proxy_handler(req, upstream_base).await } + +pub(crate) async fn handler_with_url( + req: http::Request, + upstream_base: &Url, +) -> impl IntoResponse { + proxy_handler(req, upstream_base.clone()).await +} From aea8d880caf7f906e5534f2790a7e61b81a89463 Mon Sep 17 00:00:00 2001 From: Brett Beutell Date: Mon, 28 Aug 2023 22:21:02 +0200 Subject: [PATCH 05/12] Resolve a clippy error --- src/bin/am/server.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/am/server.rs b/src/bin/am/server.rs index 975a5a5..bdf2a66 100644 --- a/src/bin/am/server.rs +++ b/src/bin/am/server.rs @@ -72,7 +72,7 @@ pub(crate) async fn start_web_server( // 4. Replace the request's URI with the modified URI. *req.uri_mut() = new_uri; } - async move { prometheus::handler_with_url(req, &*upstream_base).await } + async move { prometheus::handler_with_url(req, &upstream_base).await } }; app = app From 3b8b1dc5b912e8f571b8ac8cf0c06f2e0b827be2 Mon Sep 17 00:00:00 2001 From: Brett Beutell Date: Mon, 28 Aug 2023 22:26:41 +0200 Subject: [PATCH 06/12] Add some comments --- src/bin/am/server.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bin/am/server.rs b/src/bin/am/server.rs index bdf2a66..8e399b8 100644 --- a/src/bin/am/server.rs +++ b/src/bin/am/server.rs @@ -40,6 +40,7 @@ pub(crate) async fn start_web_server( .route("/explorer/", get(explorer::handler)) .route("/explorer/*path", get(explorer::handler)); + // Proxy `/prometheus` to the upstream (local) prometheus instance if should_enable_prometheus { app = app .route("/prometheus/*path", any(prometheus::handler)) @@ -50,8 +51,10 @@ pub(crate) async fn start_web_server( if is_proxying_prometheus { let prometheus_upstream_base = Arc::new(prometheus_proxy_url.clone().unwrap()); + // Define a handler that will proxy to an external Prometheus instance let handler = move |mut req: http::Request| { let upstream_base = prometheus_upstream_base.clone(); + // 1. Get the path and query from the request, since we need to strip out `/prometheus` let path_and_query = req .uri() .path_and_query() From 5766c444bc9f591b32491b1735969b0b941c0931 Mon Sep 17 00:00:00 2001 From: Brett Beutell Date: Wed, 30 Aug 2023 10:51:38 +0200 Subject: [PATCH 07/12] Update .gitignore Co-authored-by: Benno van den Berg --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 71e8d77..8a18b3b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,4 @@ target # Could be removed once we persist the data somewhere else data -.vscode \ No newline at end of file +.vscode From 0f3a30f97625220535a76c1c39913fbc0efc98e7 Mon Sep 17 00:00:00 2001 From: Brett Beutell Date: Wed, 30 Aug 2023 10:51:57 +0200 Subject: [PATCH 08/12] Update src/bin/am/commands/proxy.rs Co-authored-by: Benno van den Berg --- src/bin/am/commands/proxy.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/bin/am/commands/proxy.rs b/src/bin/am/commands/proxy.rs index 032103c..99780ae 100644 --- a/src/bin/am/commands/proxy.rs +++ b/src/bin/am/commands/proxy.rs @@ -22,8 +22,7 @@ pub struct CliArguments { )] listen_address: SocketAddr, - /// The url to which we should proxy requests to `/prometheus` - /// + /// The upstream Prometheus URL #[clap(long, env, alias = "prometheus-address")] prometheus_url: Option, } From 87f30a8ee48ace71026568435443792df0d22954 Mon Sep 17 00:00:00 2001 From: Brett Beutell Date: Wed, 30 Aug 2023 11:06:44 +0200 Subject: [PATCH 09/12] Failed attempt to clone request to resolve lifetime issues --- src/bin/am/server.rs | 60 ++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/src/bin/am/server.rs b/src/bin/am/server.rs index 8e399b8..a951111 100644 --- a/src/bin/am/server.rs +++ b/src/bin/am/server.rs @@ -54,28 +54,46 @@ pub(crate) async fn start_web_server( // Define a handler that will proxy to an external Prometheus instance let handler = move |mut req: http::Request| { let upstream_base = prometheus_upstream_base.clone(); - // 1. Get the path and query from the request, since we need to strip out `/prometheus` - let path_and_query = req - .uri() - .path_and_query() - .map(|pq| pq.as_str()) - .unwrap_or(""); - if let Some(stripped_path) = path_and_query.strip_prefix("/prometheus") { - // 2. Remove the `/prometheus` prefix. - let new_path_and_query = - http::uri::PathAndQuery::from_maybe_shared(stripped_path.to_string()) - .expect("Invalid path"); - - // 3. Create a new URI with the modified path. - let mut new_uri_parts = req.uri().clone().into_parts(); - new_uri_parts.path_and_query = Some(new_path_and_query); - - let new_uri = http::Uri::from_parts(new_uri_parts).expect("Invalid URI"); - - // 4. Replace the request's URI with the modified URI. - *req.uri_mut() = new_uri; + async move { + // Clone necessary parts of the request + // 1. Get the path and query from the request, since we need to strip out `/prometheus` + let uri = req.uri().clone(); + let path_and_query = uri.path_and_query().map(|pq| pq.as_str()).unwrap_or(""); + if let Some(stripped_path) = path_and_query.strip_prefix("/prometheus") { + // 2. Remove the `/prometheus` prefix. + let new_path_and_query = + http::uri::PathAndQuery::from_maybe_shared(stripped_path) + .expect("Invalid path"); + + // 3. Create a new URI with the modified path. + let mut new_uri_parts = req.uri().clone().into_parts(); + new_uri_parts.path_and_query = Some(new_path_and_query); + + let new_uri = http::Uri::from_parts(new_uri_parts).expect("Invalid URI"); + + // Clone the necessary parts of the request + // 4. Replace the request's URI with the modified URI. + + let mut cloned_req = http::Request::new(Body::empty()); + *cloned_req.method_mut() = req.method().clone(); + *cloned_req.uri_mut() = http::Uri::builder() + .path_and_query(new_path_and_query) + .build() + .expect("Invalid URI"); + *cloned_req.headers_mut() = req.headers().clone(); + + prometheus::handler_with_url(cloned_req, &upstream_base).await + } else { + prometheus::handler_with_url(req, &upstream_base).await + } + + // let mut req = http::Request::new(Body::empty()); + // *req.method_mut() = Method::GET; + // *req.uri_mut() = new_uri; + // *req.headers_mut() = headers; + + // Use the cloned URI } - async move { prometheus::handler_with_url(req, &upstream_base).await } }; app = app From b08f61c239daed99ddde2e7ddcad5311cb85dd41 Mon Sep 17 00:00:00 2001 From: Brett Beutell Date: Wed, 30 Aug 2023 11:06:56 +0200 Subject: [PATCH 10/12] Revert "Failed attempt to clone request to resolve lifetime issues" This reverts commit 87f30a8ee48ace71026568435443792df0d22954. --- src/bin/am/server.rs | 60 ++++++++++++++++---------------------------- 1 file changed, 21 insertions(+), 39 deletions(-) diff --git a/src/bin/am/server.rs b/src/bin/am/server.rs index a951111..8e399b8 100644 --- a/src/bin/am/server.rs +++ b/src/bin/am/server.rs @@ -54,46 +54,28 @@ pub(crate) async fn start_web_server( // Define a handler that will proxy to an external Prometheus instance let handler = move |mut req: http::Request| { let upstream_base = prometheus_upstream_base.clone(); - async move { - // Clone necessary parts of the request - // 1. Get the path and query from the request, since we need to strip out `/prometheus` - let uri = req.uri().clone(); - let path_and_query = uri.path_and_query().map(|pq| pq.as_str()).unwrap_or(""); - if let Some(stripped_path) = path_and_query.strip_prefix("/prometheus") { - // 2. Remove the `/prometheus` prefix. - let new_path_and_query = - http::uri::PathAndQuery::from_maybe_shared(stripped_path) - .expect("Invalid path"); - - // 3. Create a new URI with the modified path. - let mut new_uri_parts = req.uri().clone().into_parts(); - new_uri_parts.path_and_query = Some(new_path_and_query); - - let new_uri = http::Uri::from_parts(new_uri_parts).expect("Invalid URI"); - - // Clone the necessary parts of the request - // 4. Replace the request's URI with the modified URI. - - let mut cloned_req = http::Request::new(Body::empty()); - *cloned_req.method_mut() = req.method().clone(); - *cloned_req.uri_mut() = http::Uri::builder() - .path_and_query(new_path_and_query) - .build() - .expect("Invalid URI"); - *cloned_req.headers_mut() = req.headers().clone(); - - prometheus::handler_with_url(cloned_req, &upstream_base).await - } else { - prometheus::handler_with_url(req, &upstream_base).await - } - - // let mut req = http::Request::new(Body::empty()); - // *req.method_mut() = Method::GET; - // *req.uri_mut() = new_uri; - // *req.headers_mut() = headers; - - // Use the cloned URI + // 1. Get the path and query from the request, since we need to strip out `/prometheus` + let path_and_query = req + .uri() + .path_and_query() + .map(|pq| pq.as_str()) + .unwrap_or(""); + if let Some(stripped_path) = path_and_query.strip_prefix("/prometheus") { + // 2. Remove the `/prometheus` prefix. + let new_path_and_query = + http::uri::PathAndQuery::from_maybe_shared(stripped_path.to_string()) + .expect("Invalid path"); + + // 3. Create a new URI with the modified path. + let mut new_uri_parts = req.uri().clone().into_parts(); + new_uri_parts.path_and_query = Some(new_path_and_query); + + let new_uri = http::Uri::from_parts(new_uri_parts).expect("Invalid URI"); + + // 4. Replace the request's URI with the modified URI. + *req.uri_mut() = new_uri; } + async move { prometheus::handler_with_url(req, &upstream_base).await } }; app = app From df10d595102544e3647893fe29417255a0dec1af Mon Sep 17 00:00:00 2001 From: Brett Beutell Date: Wed, 30 Aug 2023 11:11:18 +0200 Subject: [PATCH 11/12] Resolve clippy error --- src/bin/am/server.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bin/am/server.rs b/src/bin/am/server.rs index 8e399b8..a7419dc 100644 --- a/src/bin/am/server.rs +++ b/src/bin/am/server.rs @@ -61,9 +61,10 @@ pub(crate) async fn start_web_server( .map(|pq| pq.as_str()) .unwrap_or(""); if let Some(stripped_path) = path_and_query.strip_prefix("/prometheus") { + let stripped_path_str = stripped_path.to_string(); // 2. Remove the `/prometheus` prefix. let new_path_and_query = - http::uri::PathAndQuery::from_maybe_shared(stripped_path.to_string()) + http::uri::PathAndQuery::from_maybe_shared(stripped_path_str) .expect("Invalid path"); // 3. Create a new URI with the modified path. From 82767eae93dfe86f30c78899861657357a3890e8 Mon Sep 17 00:00:00 2001 From: Brett Beutell Date: Wed, 30 Aug 2023 11:15:31 +0200 Subject: [PATCH 12/12] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00d6d7c..e65d4c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Update all depdencies (#124) - Fix multiarch docker image for arm64 users (#125) - Update markdown reference generator command to disable TOC (#127) +- Add `am proxy` command (#128) ## [0.3.0]