From c07954f44f4c03cc17d4a83b144667cbcbb226cf Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Tue, 2 Dec 2025 17:33:39 +0000 Subject: nip11 add icon --- src/http/mod.rs | 17 +++++++++++++++++ src/http/nip11.rs | 10 ++++++++++ 2 files changed, 27 insertions(+) (limited to 'src') diff --git a/src/http/mod.rs b/src/http/mod.rs index c47c374..5cf8dbe 100644 --- a/src/http/mod.rs +++ b/src/http/mod.rs @@ -32,6 +32,9 @@ const CORS_ALLOW_ORIGIN: &str = "*"; const CORS_ALLOW_METHODS: &str = "GET, POST"; const CORS_ALLOW_HEADERS: &str = "Content-Type"; +/// Embedded icon image (Grasp logo) +const ICON_PNG: &[u8] = include_bytes!("../../static/icon.png"); + /// Extract npub and identifier from a repository URL path (no git subpath required) /// /// Parses paths like `//.git` (for repository webpage/404) @@ -359,6 +362,20 @@ impl Service> for HttpService { } } + // Serve static icon at /icon.png + if path == "/icon.png" { + return Box::pin(async move { + Ok( + add_cors_headers(Response::builder().header("server", "ngit-grasp")) + .status(200) + .header("content-type", "image/png") + .header("cache-control", "public, max-age=86400") + .body(Full::new(Bytes::from_static(ICON_PNG))) + .unwrap(), + ) + }); + } + // Only serve landing page for root path "/", 404 for everything else let config = self.config.clone(); Box::pin(async move { diff --git a/src/http/nip11.rs b/src/http/nip11.rs index 901b676..ecb9769 100644 --- a/src/http/nip11.rs +++ b/src/http/nip11.rs @@ -34,6 +34,10 @@ pub struct RelayInformationDocument { /// Software version pub version: String, + /// Relay icon URL (NIP-11 optional field) + #[serde(skip_serializing_if = "Option::is_none")] + pub icon: Option, + // GRASP-01 Extensions (lines 11-14 of GRASP-01 spec) /// List of supported GRASPs (e.g., ["GRASP-01"]) /// Required by GRASP-01 specification line 12 @@ -67,6 +71,7 @@ impl RelayInformationDocument { Some(commit) => format!("{}-{}", env!("CARGO_PKG_VERSION"), commit), None => env!("CARGO_PKG_VERSION").to_string(), }, + icon: Some(format!("https://{}/icon.png", config.domain)), // GRASP-01 Extensions supported_grasps: vec!["GRASP-01".to_string()], @@ -113,6 +118,10 @@ mod tests { assert_eq!(doc.supported_grasps, vec!["GRASP-01"]); assert!(doc.repo_acceptance_criteria.contains("relay.example.com")); assert!(doc.curation.is_none()); + assert_eq!( + doc.icon, + Some("https://relay.example.com/icon.png".to_string()) + ); } #[test] @@ -143,5 +152,6 @@ mod tests { let parsed: serde_json::Value = serde_json::from_str(&json).expect("Invalid JSON"); assert_eq!(parsed["name"], "Test Relay"); assert_eq!(parsed["supported_grasps"][0], "GRASP-01"); + assert_eq!(parsed["icon"], "https://relay.example.com/icon.png"); } } -- cgit v1.2.3