use axum::{ Json, Router, extract::State, response::{IntoResponse, Response}, routing::get, }; use serde_json::json; use std::net::SocketAddr; #[derive(Clone)] pub struct ServerConfig { pub appview_did: String, pub appview_endpoint: String, } pub async fn run_server() { let host = std::env::var("APPVIEW_HOST").unwrap_or("0.0.0.0".to_string()); let port: u16 = std::env::var("APPVIEW_PORT") .ok() .and_then(|s| s.parse().ok()) .unwrap_or(3000); let appview_did = std::env::var("APPVIEW_DID").unwrap(); let appview_endpoint = std::env::var("APPVIEW_HOSTNAME").unwrap(); let server_config = ServerConfig { appview_did: appview_did, appview_endpoint: appview_endpoint, }; let app = Router::new() .route("/", get(say_hello_text)) .route("/.well-known/did.json", get(well_known_did_json)) .with_state(server_config); let addr: SocketAddr = format!("{host}:{port}") .parse() .expect("valid socket address"); println!("listening on {addr}"); let listener = tokio::net::TcpListener::bind(addr.to_string()) .await .unwrap(); axum::serve(listener, app).await.unwrap(); } async fn say_hello_text() -> &'static str { return "This is an appview. Work in progress. This is my appview. There are many like it, but this one is mine"; } async fn well_known_did_json(State(server_config): State) -> Response { Json(json!({ "@context": [ "https://www.w3.org/ns/did/v1", "https://w3id.org/security/multikey/v1"], "id": server_config.appview_did, "verificationMethod": [ { "id": "did:web:api.bsky.app#atproto", "type": "Multikey", "controller": "did:web:api.bsky.app", "publicKeyMultibase": "zQ3shpRzb2NDriwCSSsce6EqGxG23kVktHZc57C3NEcuNy1jg" } ], "service": [ { "id": "#bsky_notif", "type": "BskyNotificationService", "serviceEndpoint": server_config.appview_endpoint }, { "id": "#bsky_appview", "type": "BskyAppView", "serviceEndpoint": server_config.appview_endpoint } ] })) .into_response() }