1mod graphql;
4mod gsp;
5pub mod mcp;
6mod openai;
7mod openai_v1;
8mod prometheus;
9mod sparql;
10mod well_known;
11
12#[cfg(feature = "app")]
13mod app;
14
15use axum::{response::Json, routing::get, Router};
16use tokio::net::{TcpListener, ToSocketAddrs};
17use tokio_util::sync::CancellationToken;
18use tower_http::cors::CorsLayer;
19
20pub fn routes() -> Router {
21 let mcp_server = mcp::Server::default();
22 let router = Router::new()
23 .merge(graphql::routes())
24 .merge(gsp::routes())
25 .merge(mcp::routes().with_state(mcp_server))
26 .merge(openai::routes())
27 .merge(prometheus::routes())
28 .merge(sparql::routes())
29 .merge(well_known::routes());
30
31 #[cfg(feature = "app")]
32 let router = router.merge(app::routes());
33
34 #[cfg(feature = "tracing")]
35 let router = router.layer(
36 tower_http::trace::TraceLayer::new_for_http()
37 .make_span_with(tower_http::trace::DefaultMakeSpan::new().include_headers(true))
38 .on_request(
39 |request: &http::Request<axum::body::Body>, _span: &tracing::Span| {
40 tracing::info!(
41 "Received a {} {} request",
42 request.method(),
43 request.uri().path()
44 );
45 },
46 ),
47 );
48
49 router
50 .layer(CorsLayer::permissive())
51 .route("/", get(http_handler))
52}
53
54pub async fn start(addr: impl ToSocketAddrs, cancel: CancellationToken) -> std::io::Result<()> {
55 let listener = TcpListener::bind(addr).await?;
56
57 #[cfg(feature = "tracing")]
58 tracing::info!(
59 "Listening for HTTP requests on {}...",
60 listener.local_addr().unwrap()
61 );
62
63 axum::serve(listener, routes())
64 .with_graceful_shutdown(cancel.cancelled_owned())
65 .await
66}
67
68async fn http_handler() -> Json<&'static str> {
69 Json("Hello, world!") }