Gnosco is a Rust-based escrow and badging application that integrates with the AT Protocol ecosystem..
at main 93 lines 3.3 kB view raw
1//! HTTP server setup with routing and middleware. 2//! 3//! Configures OAuth routes (`/oauth/*`), main interface (`/`), and static files 4//! with CORS, tracing, timeouts, and internationalization middleware. 5//! 6//! ## Route Structure 7//! - `GET /`: Main application interface 8//! - `GET|POST /oauth/login`: OAuth authentication initiation 9//! - `GET /oauth/callback`: OAuth authentication completion 10//! - `GET /oauth/client-metadata.json`: OAuth client metadata 11//! - `GET /.well-known/jwks.json`: JSON Web Key Set 12//! - `POST /xrpc/community.lexicon.escrow.submitSignedRecord`: XRPC endpoint 13//! - Static file serving for assets 14//! 15//! ## Middleware Stack 16//! - Request tracing and error logging 17//! - 30-second request timeout 18//! - CORS headers for external base domain 19//! - HTMX auto-vary support for dynamic responses 20 21use std::time::Duration; 22 23use axum::{ 24 Router, 25 http::HeaderValue, 26 routing::{get, post}, 27}; 28use axum_htmx::AutoVaryLayer; 29use http::{ 30 Method, 31 header::{ACCEPT, ACCEPT_LANGUAGE}, 32}; 33use tower_http::trace::TraceLayer; 34use tower_http::{classify::ServerErrorsFailureClass, timeout::TimeoutLayer}; 35use tower_http::{cors::CorsLayer, services::ServeDir}; 36use tracing::Span; 37 38use atproto_oauth_axum::{handle_jwks::handle_oauth_jwks, handler_metadata::handle_oauth_metadata}; 39 40use crate::http::{ 41 context::WebContext, handle_index::handle_index, handle_oauth_callback::handle_oauth_callback, 42 handle_oauth_login::handle_oauth_login, 43 handle_xrpc_submit_signed_record::handle_xrpc_submit_signed_record, 44}; 45 46pub fn build_router(web_context: WebContext) -> Router { 47 let serve_dir = ServeDir::new(web_context.config.http_static_path.clone()); 48 49 let mut router = Router::new() 50 .route("/", get(handle_index)) 51 .route("/oauth/login", get(handle_oauth_login)) 52 .route("/oauth/login", post(handle_oauth_login)) 53 .route("/oauth/callback", get(handle_oauth_callback)) 54 .route( 55 "/xrpc/community.lexicon.ngerakines.escrow.submitSignedRecord", 56 post(handle_xrpc_submit_signed_record), 57 ); 58 59 // Only add PDS-specific OAuth endpoints if using PDS backend 60 if matches!( 61 web_context.config.oauth_backend, 62 crate::config::OAuthBackend::Pds 63 ) { 64 router = router 65 .route("/oauth/client-metadata.json", get(handle_oauth_metadata)) 66 .route("/.well-known/jwks.json", get(handle_oauth_jwks)); 67 } 68 69 router 70 .fallback_service(serve_dir) 71 .layer(( 72 TraceLayer::new_for_http().on_failure( 73 |err: ServerErrorsFailureClass, _latency: Duration, _span: &Span| { 74 tracing::error!(error = ?err, "Unhandled error: {err}"); 75 }, 76 ), 77 TimeoutLayer::new(Duration::from_secs(30)), 78 )) 79 .layer( 80 CorsLayer::new() 81 .allow_origin( 82 web_context 83 .config 84 .external_base 85 .parse::<HeaderValue>() 86 .unwrap(), 87 ) 88 .allow_methods([Method::GET, Method::POST]) 89 .allow_headers([ACCEPT_LANGUAGE, ACCEPT]), 90 ) 91 .layer(AutoVaryLayer) 92 .with_state(web_context.clone()) 93}