relay-core-http 0.1.1

REST/SSE HTTP API adapter for relay-core: language-agnostic integration boundary for external tools
Documentation
use std::sync::Arc;
use axum::{
    Json, Router,
    extract::{Query, State},
    http::{HeaderValue, StatusCode, header::CONTENT_TYPE},
    response::IntoResponse,
    routing::get,
};
use relay_core_runtime::{
    CoreAuditQuery, CoreAuditSnapshot, CoreMetrics, CoreState, CoreStatusSnapshot,
    audit::{AuditActor, AuditEventKind, AuditOutcome},
};
use serde::Deserialize;

/// GET /api/v1/metrics
pub fn router(state: Arc<CoreState>) -> Router {
    Router::new()
        .route("/api/v1/metrics", get(get_metrics))
        .route("/api/v1/metrics/prometheus", get(get_metrics_prometheus))
        .route("/api/v1/audit", get(get_audit))
        .route("/api/v1/status", get(get_status))
        .with_state(state)
}

async fn get_metrics(State(state): State<Arc<CoreState>>) -> Json<CoreMetrics> {
    Json(state.get_metrics().await)
}

async fn get_metrics_prometheus(State(state): State<Arc<CoreState>>) -> impl IntoResponse {
    (
        StatusCode::OK,
        [(
            CONTENT_TYPE,
            HeaderValue::from_static("text/plain; version=0.0.4; charset=utf-8"),
        )],
        state.get_metrics_prometheus_text().await,
    )
}

async fn get_status(State(state): State<Arc<CoreState>>) -> Json<CoreStatusSnapshot> {
    Json(state.status_snapshot())
}

#[derive(Debug, Deserialize)]
struct AuditQueryParams {
    since_ms: Option<u64>,
    until_ms: Option<u64>,
    actor: Option<String>,
    kind: Option<String>,
    outcome: Option<String>,
    limit: Option<usize>,
}

async fn get_audit(
    State(state): State<Arc<CoreState>>,
    Query(params): Query<AuditQueryParams>,
) -> Json<CoreAuditSnapshot> {
    let query = CoreAuditQuery {
        since_ms: params.since_ms,
        until_ms: params.until_ms,
        actor: params.actor.as_deref().and_then(|v| v.parse::<AuditActor>().ok()),
        kind: params
            .kind
            .as_deref()
            .and_then(|v| v.parse::<AuditEventKind>().ok()),
        outcome: params
            .outcome
            .as_deref()
            .and_then(|v| v.parse::<AuditOutcome>().ok()),
        limit: params.limit.unwrap_or(50),
    };
    Json(state.query_audit_snapshot(query).await)
}