upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/http/mod.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2026-01-07 21:35:56 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-01-07 21:35:56 +0000
commit457e296d90e2f7c2808e216f2ef0608b70f76553 (patch)
tree8b6529cb9db3bb562842a4cfb0bf8c217ed7db1a /src/http/mod.rs
parent0550b3229f35ef3ee125bac47d85bbd08d1250b1 (diff)
Add Git protocol v2 support to fix modern git client compatibility
Modern git clients (2.51.0+) default to protocol v2 and send the Git-Protocol header. The server must pass this to git processes via the GIT_PROTOCOL environment variable for proper negotiation. Changes: - Extract Git-Protocol header in HTTP layer (src/http/mod.rs) - Pass git_protocol parameter through all handler functions - Set GIT_PROTOCOL env var when spawning git subprocesses - Update all tests to pass None for backward compatibility This fixes hangs/timeouts when modern git clients connect to the server. Fixes issue discovered in work/2025-01-07-pr-clone-tag-sync-investigation.md
Diffstat (limited to 'src/http/mod.rs')
-rw-r--r--src/http/mod.rs27
1 files changed, 23 insertions, 4 deletions
diff --git a/src/http/mod.rs b/src/http/mod.rs
index e2caf5d..9172e86 100644
--- a/src/http/mod.rs
+++ b/src/http/mod.rs
@@ -152,13 +152,21 @@ impl Service<Request<Incoming>> for HttpService {
152 let identifier = identifier.to_string(); 152 let identifier = identifier.to_string();
153 let subpath = subpath.to_string(); 153 let subpath = subpath.to_string();
154 154
155 // Extract Git-Protocol header for protocol v2 support
156 let git_protocol = req
157 .headers()
158 .get("git-protocol")
159 .and_then(|v| v.to_str().ok())
160 .map(|s| s.to_string());
161
155 tracing::debug!( 162 tracing::debug!(
156 "Git request: {} {} (npub={}, id={}, subpath={})", 163 "Git request: {} {} (npub={}, id={}, subpath={}, protocol={:?})",
157 method, 164 method,
158 path, 165 path,
159 npub, 166 npub,
160 identifier, 167 identifier,
161 subpath 168 subpath,
169 git_protocol
162 ); 170 );
163 171
164 let repo_path = git::resolve_repo_path(&git_data_path, &npub, &identifier); 172 let repo_path = git::resolve_repo_path(&git_data_path, &npub, &identifier);
@@ -185,7 +193,12 @@ impl Service<Request<Incoming>> for HttpService {
185 193
186 match service { 194 match service {
187 Some(svc) => { 195 Some(svc) => {
188 let result = git::handlers::handle_info_refs(repo_path, svc).await; 196 let result = git::handlers::handle_info_refs(
197 repo_path,
198 svc,
199 git_protocol.as_deref(),
200 )
201 .await;
189 // Track operation 202 // Track operation
190 if let Some(ref m) = metrics_clone { 203 if let Some(ref m) = metrics_clone {
191 let status = if result.is_ok() { "success" } else { "error" }; 204 let status = if result.is_ok() { "success" } else { "error" };
@@ -203,7 +216,12 @@ impl Service<Request<Incoming>> for HttpService {
203 216
204 // POST /git-upload-pack (clone/fetch) 217 // POST /git-upload-pack (clone/fetch)
205 (m, "git-upload-pack") if m == Method::POST => { 218 (m, "git-upload-pack") if m == Method::POST => {
206 let result = git::handlers::handle_upload_pack(repo_path, body_bytes).await; 219 let result = git::handlers::handle_upload_pack(
220 repo_path,
221 body_bytes,
222 git_protocol.as_deref(),
223 )
224 .await;
207 if let Some(ref m) = metrics_clone { 225 if let Some(ref m) = metrics_clone {
208 let status = if result.is_ok() { "success" } else { "error" }; 226 let status = if result.is_ok() { "success" } else { "error" };
209 m.record_git_operation("clone", status); 227 m.record_git_operation("clone", status);
@@ -238,6 +256,7 @@ impl Service<Request<Incoming>> for HttpService {
238 &owner_pubkey_hex, 256 &owner_pubkey_hex,
239 purgatory.clone(), 257 purgatory.clone(),
240 &git_data_path, 258 &git_data_path,
259 git_protocol.as_deref(),
241 ) 260 )
242 .await; 261 .await;
243 262