upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/http/mod.rs17
-rw-r--r--src/http/nip11.rs10
2 files changed, 27 insertions, 0 deletions
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 = "*";
32const CORS_ALLOW_METHODS: &str = "GET, POST"; 32const CORS_ALLOW_METHODS: &str = "GET, POST";
33const CORS_ALLOW_HEADERS: &str = "Content-Type"; 33const CORS_ALLOW_HEADERS: &str = "Content-Type";
34 34
35/// Embedded icon image (Grasp logo)
36const ICON_PNG: &[u8] = include_bytes!("../../static/icon.png");
37
35/// Extract npub and identifier from a repository URL path (no git subpath required) 38/// Extract npub and identifier from a repository URL path (no git subpath required)
36/// 39///
37/// Parses paths like `/<npub>/<identifier>.git` (for repository webpage/404) 40/// Parses paths like `/<npub>/<identifier>.git` (for repository webpage/404)
@@ -359,6 +362,20 @@ impl Service<Request<Incoming>> for HttpService {
359 } 362 }
360 } 363 }
361 364
365 // Serve static icon at /icon.png
366 if path == "/icon.png" {
367 return Box::pin(async move {
368 Ok(
369 add_cors_headers(Response::builder().header("server", "ngit-grasp"))
370 .status(200)
371 .header("content-type", "image/png")
372 .header("cache-control", "public, max-age=86400")
373 .body(Full::new(Bytes::from_static(ICON_PNG)))
374 .unwrap(),
375 )
376 });
377 }
378
362 // Only serve landing page for root path "/", 404 for everything else 379 // Only serve landing page for root path "/", 404 for everything else
363 let config = self.config.clone(); 380 let config = self.config.clone();
364 Box::pin(async move { 381 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 {
34 /// Software version 34 /// Software version
35 pub version: String, 35 pub version: String,
36 36
37 /// Relay icon URL (NIP-11 optional field)
38 #[serde(skip_serializing_if = "Option::is_none")]
39 pub icon: Option<String>,
40
37 // GRASP-01 Extensions (lines 11-14 of GRASP-01 spec) 41 // GRASP-01 Extensions (lines 11-14 of GRASP-01 spec)
38 /// List of supported GRASPs (e.g., ["GRASP-01"]) 42 /// List of supported GRASPs (e.g., ["GRASP-01"])
39 /// Required by GRASP-01 specification line 12 43 /// Required by GRASP-01 specification line 12
@@ -67,6 +71,7 @@ impl RelayInformationDocument {
67 Some(commit) => format!("{}-{}", env!("CARGO_PKG_VERSION"), commit), 71 Some(commit) => format!("{}-{}", env!("CARGO_PKG_VERSION"), commit),
68 None => env!("CARGO_PKG_VERSION").to_string(), 72 None => env!("CARGO_PKG_VERSION").to_string(),
69 }, 73 },
74 icon: Some(format!("https://{}/icon.png", config.domain)),
70 75
71 // GRASP-01 Extensions 76 // GRASP-01 Extensions
72 supported_grasps: vec!["GRASP-01".to_string()], 77 supported_grasps: vec!["GRASP-01".to_string()],
@@ -113,6 +118,10 @@ mod tests {
113 assert_eq!(doc.supported_grasps, vec!["GRASP-01"]); 118 assert_eq!(doc.supported_grasps, vec!["GRASP-01"]);
114 assert!(doc.repo_acceptance_criteria.contains("relay.example.com")); 119 assert!(doc.repo_acceptance_criteria.contains("relay.example.com"));
115 assert!(doc.curation.is_none()); 120 assert!(doc.curation.is_none());
121 assert_eq!(
122 doc.icon,
123 Some("https://relay.example.com/icon.png".to_string())
124 );
116 } 125 }
117 126
118 #[test] 127 #[test]
@@ -143,5 +152,6 @@ mod tests {
143 let parsed: serde_json::Value = serde_json::from_str(&json).expect("Invalid JSON"); 152 let parsed: serde_json::Value = serde_json::from_str(&json).expect("Invalid JSON");
144 assert_eq!(parsed["name"], "Test Relay"); 153 assert_eq!(parsed["name"], "Test Relay");
145 assert_eq!(parsed["supported_grasps"][0], "GRASP-01"); 154 assert_eq!(parsed["supported_grasps"][0], "GRASP-01");
155 assert_eq!(parsed["icon"], "https://relay.example.com/icon.png");
146 } 156 }
147} 157}