This commit is contained in:
Andras Schmelczer 2026-05-16 16:26:36 +01:00
parent e9a06417ad
commit 5e5d9f9a1c
16 changed files with 280 additions and 44 deletions

View file

@ -1,10 +1,11 @@
use axum::body::Body;
use axum::extract::Request;
use axum::extract::{ConnectInfo, Request};
use axum::http::StatusCode;
use axum::middleware::Next;
use axum::response::{IntoResponse, Response};
use metrics::{counter, gauge, histogram};
use metrics_exporter_prometheus::{Matcher, PrometheusBuilder, PrometheusHandle};
use std::net::{IpAddr, SocketAddr};
use std::time::Instant;
/// Initialize the Prometheus metrics exporter and return a handle for rendering metrics.
@ -144,17 +145,39 @@ fn normalize_path(path: &str) -> String {
"/other".to_string()
}
/// Handler for the /metrics endpoint.
pub async fn metrics_handler(handle: PrometheusHandle) -> impl IntoResponse {
// Update process metrics before rendering
/// Handler for the /metrics endpoint. Only accepts requests from peers on the
/// same private network (loopback, RFC1918, or IPv6 unique/link-local).
pub async fn metrics_handler(
handle: PrometheusHandle,
ConnectInfo(peer): ConnectInfo<SocketAddr>,
) -> Response {
if !is_same_network(peer.ip()) {
return StatusCode::FORBIDDEN.into_response();
}
update_process_metrics();
match handle.render() {
output if !output.is_empty() => (StatusCode::OK, output),
output if !output.is_empty() => (StatusCode::OK, output).into_response(),
_ => (
StatusCode::INTERNAL_SERVER_ERROR,
"Failed to render metrics".to_string(),
),
)
.into_response(),
}
}
fn is_same_network(ip: IpAddr) -> bool {
match ip {
IpAddr::V4(v4) => v4.is_loopback() || v4.is_private() || v4.is_link_local(),
IpAddr::V6(v6) => {
v6.is_loopback()
|| (v6.segments()[0] & 0xfe00) == 0xfc00
|| (v6.segments()[0] & 0xffc0) == 0xfe80
|| v6.to_ipv4_mapped().is_some_and(|v4| {
v4.is_loopback() || v4.is_private() || v4.is_link_local()
})
}
}
}