this repo has no description
1mod api;
2mod state;
3mod auth;
4mod repo;
5
6use axum::{
7 extract::State,
8 routing::{get, post},
9 Router,
10 Json,
11 response::IntoResponse,
12 http::StatusCode,
13};
14use serde_json::json;
15use std::net::SocketAddr;
16use state::AppState;
17use tracing::{info, error};
18
19#[tokio::main]
20async fn main() {
21 dotenvy::dotenv().ok();
22 tracing_subscriber::fmt::init();
23
24 let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
25
26 let pool = sqlx::postgres::PgPoolOptions::new()
27 .max_connections(5)
28 .connect(&database_url)
29 .await
30 .expect("Failed to connect to Postgres");
31
32 sqlx::migrate!("./migrations")
33 .run(&pool)
34 .await
35 .expect("Failed to run migrations");
36
37 let state = AppState::new(pool);
38
39 let app = Router::new()
40 .route("/health", get(health))
41 .route("/xrpc/com.atproto.server.describeServer", get(describe_server))
42 .route("/xrpc/com.atproto.server.createAccount", post(api::server::create_account))
43 .route("/xrpc/com.atproto.server.createSession", post(api::server::create_session))
44 .route("/xrpc/com.atproto.server.getSession", get(api::server::get_session))
45 .route("/xrpc/com.atproto.server.deleteSession", post(api::server::delete_session))
46 .route("/xrpc/com.atproto.server.refreshSession", post(api::server::refresh_session))
47 .route("/xrpc/com.atproto.repo.createRecord", post(api::repo::create_record))
48 .with_state(state);
49
50 let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
51 info!("listening on {}", addr);
52 let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
53 axum::serve(listener, app).await.unwrap();
54}
55
56async fn health(State(state): State<AppState>) -> impl IntoResponse {
57 match sqlx::query("SELECT 1").execute(&state.db).await {
58 Ok(_) => (StatusCode::OK, "OK"),
59 Err(e) => {
60 error!("Health check failed: {:?}", e);
61 (StatusCode::SERVICE_UNAVAILABLE, "Service Unavailable")
62 }
63 }
64}
65
66async fn describe_server() -> impl IntoResponse {
67 let domains_str = std::env::var("AVAILABLE_USER_DOMAINS").unwrap_or_else(|_| "example.com".to_string());
68 let domains: Vec<&str> = domains_str.split(',').map(|s| s.trim()).collect();
69
70 Json(json!({
71 "availableUserDomains": domains
72 }))
73}