at protocol indexer with flexible filtering, xrpc queries, and a cursor-backed event stream, built on fjall
at-protocol
atproto
indexer
rust
fjall
1use crate::state::AppState;
2use axum::{Router, routing::get};
3use std::{net::SocketAddr, sync::Arc};
4use tower_http::cors::CorsLayer;
5use tower_http::trace::TraceLayer;
6
7mod debug;
8mod filter;
9mod repos;
10mod stats;
11mod stream;
12mod xrpc;
13
14pub async fn serve(state: Arc<AppState>, port: u16) -> miette::Result<()> {
15 let app = Router::new()
16 .route("/health", get(|| async { "OK" }))
17 .route("/stats", get(stats::get_stats))
18 .nest("/stream", stream::router())
19 .merge(xrpc::router())
20 .merge(filter::router())
21 .merge(repos::router())
22 .with_state(state)
23 .layer(TraceLayer::new_for_http())
24 .layer(CorsLayer::permissive());
25
26 let listener = tokio::net::TcpListener::bind(format!("0.0.0.0:{port}"))
27 .await
28 .map_err(|e| miette::miette!("failed to bind to port {port}: {e}"))?;
29
30 tracing::info!("API server listening on {}", listener.local_addr().unwrap());
31
32 axum::serve(
33 listener,
34 app.into_make_service_with_connect_info::<SocketAddr>(),
35 )
36 .await
37 .map_err(|e| miette::miette!("axum server error: {e}"))?;
38
39 Ok(())
40}
41
42pub async fn serve_debug(state: Arc<AppState>, port: u16) -> miette::Result<()> {
43 let app = debug::router()
44 .with_state(state)
45 .layer(TraceLayer::new_for_http());
46
47 let listener = tokio::net::TcpListener::bind(format!("127.0.0.1:{port}"))
48 .await
49 .map_err(|e| miette::miette!("failed to bind debug server to port {port}: {e}"))?;
50
51 tracing::info!(
52 "debug server listening on {}",
53 listener.local_addr().unwrap()
54 );
55
56 axum::serve(
57 listener,
58 app.into_make_service_with_connect_info::<SocketAddr>(),
59 )
60 .await
61 .map_err(|e| miette::miette!("debug server error: {e}"))?;
62
63 Ok(())
64}