upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/http
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2025-11-28 10:31:46 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2025-11-28 10:31:46 +0000
commit744094c61d6e65892bcdb5a29b90b845ce87559f (patch)
tree61c53f0ab93901b2b3d5378f7d13c3ac2b6dea98 /src/http
parent4da51a8adb94f2979c0a911157f26596c1ee2cb5 (diff)
fix maintainer recursion
Diffstat (limited to 'src/http')
-rw-r--r--src/http/mod.rs51
1 files changed, 38 insertions, 13 deletions
diff --git a/src/http/mod.rs b/src/http/mod.rs
index befa006..07b47ee 100644
--- a/src/http/mod.rs
+++ b/src/http/mod.rs
@@ -7,6 +7,7 @@ pub mod nip11;
7use std::future::Future; 7use std::future::Future;
8use std::net::SocketAddr; 8use std::net::SocketAddr;
9use std::pin::Pin; 9use std::pin::Pin;
10use std::sync::Arc;
10 11
11use hyper::body::{Bytes, Incoming}; 12use hyper::body::{Bytes, Incoming};
12use hyper::header::{CONNECTION, SEC_WEBSOCKET_ACCEPT, UPGRADE}; 13use hyper::header::{CONNECTION, SEC_WEBSOCKET_ACCEPT, UPGRADE};
@@ -17,6 +18,8 @@ use hyper_util::rt::TokioIo;
17use http_body_util::{BodyExt, Full}; 18use http_body_util::{BodyExt, Full};
18use nostr_sdk::hashes::sha1::Hash as Sha1Hash; 19use nostr_sdk::hashes::sha1::Hash as Sha1Hash;
19use nostr_sdk::hashes::{Hash, HashEngine}; 20use nostr_sdk::hashes::{Hash, HashEngine};
21use nostr_sdk::PublicKey;
22use nostr_relay_builder::prelude::MemoryDatabase;
20use nostr_relay_builder::LocalRelay; 23use nostr_relay_builder::LocalRelay;
21use tokio::net::TcpListener; 24use tokio::net::TcpListener;
22use base64::Engine; 25use base64::Engine;
@@ -42,14 +45,17 @@ struct HttpService {
42 relay: LocalRelay, 45 relay: LocalRelay,
43 config: Config, 46 config: Config,
44 remote: SocketAddr, 47 remote: SocketAddr,
48 /// Database reference for direct queries (e.g., push authorization)
49 database: Arc<MemoryDatabase>,
45} 50}
46 51
47impl HttpService { 52impl HttpService {
48 fn new(relay: LocalRelay, config: Config, remote: SocketAddr) -> Self { 53 fn new(relay: LocalRelay, config: Config, remote: SocketAddr, database: Arc<MemoryDatabase>) -> Self {
49 Self { 54 Self {
50 relay, 55 relay,
51 config, 56 config,
52 remote, 57 remote,
58 database,
53 } 59 }
54 } 60 }
55} 61}
@@ -65,7 +71,7 @@ impl Service<Request<Incoming>> for HttpService {
65 let query = req.uri().query().map(|s| s.to_string()); 71 let query = req.uri().query().map(|s| s.to_string());
66 let method = req.method().clone(); 72 let method = req.method().clone();
67 let git_data_path = self.config.git_data_path.clone(); 73 let git_data_path = self.config.git_data_path.clone();
68 let relay_domain = self.config.domain.clone(); 74 let database = self.database.clone();
69 75
70 // Handle OPTIONS preflight requests (CORS) 76 // Handle OPTIONS preflight requests (CORS)
71 // GRASP-01 spec line 47: Respond to OPTIONS with 204 No Content 77 // GRASP-01 spec line 47: Respond to OPTIONS with 204 No Content
@@ -118,17 +124,27 @@ impl Service<Request<Incoming>> for HttpService {
118 git::handlers::handle_upload_pack(repo_path, body_bytes).await 124 git::handlers::handle_upload_pack(repo_path, body_bytes).await
119 } 125 }
120 126
121 // POST /git-receive-pack (push) - with GRASP authorization 127 // POST /git-receive-pack (push) - with GRASP authorization via database
122 (m, "git-receive-pack") if m == Method::POST => { 128 (m, "git-receive-pack") if m == Method::POST => {
123 // Build authorization parameters for GRASP validation 129 // Convert npub (bech32) to hex pubkey for authorization
124 // Use ws:// protocol for relay since we're connecting internally 130 let owner_pubkey_hex = match PublicKey::parse(&npub) {
125 let relay_url = format!("ws://{}", relay_domain); 131 Ok(pk) => pk.to_hex(),
126 let auth_params = git::handlers::PushAuthParams { 132 Err(e) => {
127 relay_url, 133 tracing::warn!("Invalid npub in URL {}: {}", npub, e);
128 owner_npub: npub.clone(), 134 return Ok(add_cors_headers(Response::builder())
129 identifier: identifier.clone(), 135 .status(hyper::StatusCode::BAD_REQUEST)
136 .body(Full::new(Bytes::from(format!("Invalid npub: {}", e))))
137 .unwrap());
138 }
130 }; 139 };
131 git::handlers::handle_receive_pack(repo_path, body_bytes.clone(), Some(auth_params)).await 140
141 git::handlers::handle_receive_pack(
142 repo_path,
143 body_bytes.clone(),
144 Some(database.clone()),
145 &identifier,
146 &owner_pubkey_hex,
147 ).await
132 } 148 }
133 149
134 _ => { 150 _ => {
@@ -255,7 +271,16 @@ fn derive_accept_key(request_key: &[u8]) -> String {
255} 271}
256 272
257/// Start the HTTP server with integrated Nostr relay 273/// Start the HTTP server with integrated Nostr relay
258pub async fn run_server(config: Config, relay: LocalRelay) -> anyhow::Result<()> { 274///
275/// # Arguments
276/// * `config` - Server configuration
277/// * `relay` - The LocalRelay for WebSocket connections
278/// * `database` - The database for direct queries (e.g., push authorization)
279pub async fn run_server(
280 config: Config,
281 relay: LocalRelay,
282 database: Arc<MemoryDatabase>,
283) -> anyhow::Result<()> {
259 let bind_addr: SocketAddr = config.bind_address.parse()?; 284 let bind_addr: SocketAddr = config.bind_address.parse()?;
260 285
261 tracing::info!("Starting HTTP server on {}", bind_addr); 286 tracing::info!("Starting HTTP server on {}", bind_addr);
@@ -267,7 +292,7 @@ pub async fn run_server(config: Config, relay: LocalRelay) -> anyhow::Result<()>
267 loop { 292 loop {
268 let (socket, addr) = listener.accept().await?; 293 let (socket, addr) = listener.accept().await?;
269 let io = TokioIo::new(socket); 294 let io = TokioIo::new(socket);
270 let service = HttpService::new(relay.clone(), config.clone(), addr); 295 let service = HttpService::new(relay.clone(), config.clone(), addr, database.clone());
271 296
272 tokio::spawn(async move { 297 tokio::spawn(async move {
273 if let Err(e) = http1::Builder::new() 298 if let Err(e) = http1::Builder::new()