Skip to main content

envoy/http/
router.rs

1use axum::{routing::get, Router};
2use tower_http::request_id::{MakeRequestUuid, PropagateRequestIdLayer, SetRequestIdLayer};
3use tower_http::trace::TraceLayer;
4
5use crate::http::handlers::*;
6use crate::http::middleware::rate_limit_middleware;
7use crate::http::state::SharedState;
8use crate::http::ws::ws_handler;
9
10fn build_base_routes() -> Router<SharedState> {
11    Router::new()
12        .route("/agents", get(list_agents).post(register_agent))
13        .route(
14            "/agents/{agent_id}",
15            get(get_agent).delete(disconnect_agent),
16        )
17        .route(
18            "/agents/{agent_id}/retire",
19            axum::routing::post(retire_agent),
20        )
21        .route("/agents/{agent_id}/messages/pending", get(pending_messages))
22        .route("/messages", get(poll_messages).post(send_message))
23        .route("/messages/{message_id}", get(get_message))
24        .route(
25            "/messages/{message_id}/ack",
26            axum::routing::post(ack_message),
27        )
28        .route("/agents/{agent_id}/circuit", get(get_circuit))
29        .route(
30            "/agents/{agent_id}/circuit/failure",
31            axum::routing::post(record_circuit_failure),
32        )
33        .route("/health", get(health))
34        .route("/stats", get(stats))
35        .route("/heartbeat", axum::routing::post(heartbeat))
36        .route("/dependencies", axum::routing::post(create_dependency))
37        .route("/dependencies/blocker/{agent_id}", get(get_blocker_deps))
38        .route(
39            "/dependencies/dependent/{agent_id}",
40            get(get_dependent_deps),
41        )
42        .route(
43            "/dependencies/{dep_id}/resolve",
44            axum::routing::post(resolve_dependency),
45        )
46        .route(
47            "/nudge-config",
48            get(get_nudge_config).post(update_nudge_config),
49        )
50        .route("/events/hook", axum::routing::post(ingest_hook_event))
51        .route("/events/gate", axum::routing::post(ingest_gate_event))
52        .route("/events/ci", axum::routing::post(ingest_ci_event))
53        .route("/events/doc", axum::routing::post(ingest_doc_event))
54        .route("/events/verify", axum::routing::post(ingest_verify_event))
55        .route("/events", get(query_events))
56        .route("/audit", get(query_audit))
57        .route("/tasks/propose", axum::routing::post(propose_task))
58        .route("/tasks/claim-next", axum::routing::post(claim_next_task))
59        .route("/tasks/{id}/claim", axum::routing::post(claim_task))
60        .route("/tasks/{id}/state", axum::routing::post(update_task_state))
61        .route("/tasks/{id}/audit", get(query_task_audit))
62        .route("/tasks/{id}", get(get_task))
63        .route("/tasks", get(list_tasks))
64        .route("/subscriptions", axum::routing::post(subscribe_agent))
65        .route(
66            "/subscriptions/{agent_id}/{project}",
67            axum::routing::delete(unsubscribe_agent),
68        )
69        .route("/subscriptions/{agent_id}", get(list_subscriptions))
70        .route(
71            "/projects/{name}/config",
72            get(get_project_config).post(set_project_config),
73        )
74        .route("/ws/{agent_id}", get(ws_handler))
75        .route("/metrics", get(crate::metrics::metrics_endpoint))
76}
77
78#[cfg(feature = "atheneum")]
79fn add_atheneum_routes(routes: Router<SharedState>) -> Router<SharedState> {
80    crate::atheneum_bridge::add_atheneum_routes(routes)
81}
82
83/// Build the envoy HTTP router with rate limiting, request tracing, and request IDs.
84pub fn build_router(state: SharedState) -> Router {
85    let routes = build_base_routes();
86
87    #[cfg(feature = "atheneum")]
88    let routes = add_atheneum_routes(routes);
89
90    routes
91        .with_state(state.clone())
92        .layer(axum::extract::DefaultBodyLimit::max(1_048_576))
93        .layer(axum::middleware::from_fn_with_state(
94            state,
95            rate_limit_middleware,
96        ))
97        .layer(TraceLayer::new_for_http())
98        .layer(PropagateRequestIdLayer::x_request_id())
99        .layer(SetRequestIdLayer::x_request_id(MakeRequestUuid))
100        .layer(axum::middleware::from_fn(
101            crate::metrics::metrics_middleware,
102        ))
103}
104
105/// Build the router without rate limiting (for tests).
106pub fn build_router_unlimited(state: SharedState) -> Router {
107    let routes = build_base_routes();
108
109    #[cfg(feature = "atheneum")]
110    let routes = add_atheneum_routes(routes);
111
112    routes.with_state(state)
113}