git_http_backend/actix/
refs.rs1use crate::GitConfig;
2use actix_web::http::header::HeaderValue;
3use actix_web::http::StatusCode;
4use actix_web::{web, HttpRequest, HttpResponseBuilder, Responder};
5use std::process::Command;
6use tracing::info;
7
8pub async fn info_refs(request: HttpRequest, service: web::Data<impl GitConfig>) -> impl Responder {
9 let uri = request.uri();
10 let path = uri.path().to_string().replace("/info/refs", "");
11 let path = service.rewrite(path).await;
12 let query = uri.query().unwrap_or("");
13 let service = query.split('=').map(|x| x.to_string()).collect::<Vec<_>>();
14 let service = service[1].clone();
15 if !(service != "git-upload-pack" || service != "git-receive-pack") {
16 return Err(actix_web::error::ErrorUnsupportedMediaType(
17 "service not git-upload-pack",
18 ));
19 }
20 let service_name = service.replace("git-", "");
21 let version = request
22 .headers()
23 .get("Git-Protocol")
24 .unwrap_or(&HeaderValue::from_str("").unwrap())
25 .to_str()
26 .map(|s| s.to_string())
27 .unwrap_or("".to_string());
28 let mut cmd = Command::new("git");
29 cmd.arg(service_name.clone());
30 cmd.arg("--stateless-rpc");
31 cmd.arg("--advertise-refs");
32 cmd.arg(".");
33 cmd.current_dir(path);
34 if !version.is_empty() {
35 cmd.env("GIT_PROTOCOL", version.clone());
36 }
37
38 let output = match cmd.output() {
39 Ok(output) => {
40 info!("Command status: {:?}", output.status);
41 output
42 }
43 Err(e) => {
44 eprintln!("Error running command: {}", e);
45 return Err(actix_web::error::ErrorInternalServerError(
46 "Error running command",
47 ));
48 }
49 };
50 let mut resp = HttpResponseBuilder::new(StatusCode::OK);
51 resp.append_header((
52 "Content-Type",
53 format!("application/x-git-{}-advertisement", service_name),
54 ));
55 resp.append_header(("Pragma", "no-cache"));
56 resp.append_header(("Cache-Control", "no-cache, max-age=0, must-revalidate"));
57 resp.append_header(("Expires", "Fri, 01 Jan 1980 00:00:00 GMT"));
58
59 let mut body = String::new();
60
61 match service_name.as_str() {
62 "upload-pack" => {
63 body.push_str(&"001e# service=git-upload-pack\n".to_string());
64 body.push_str("0000");
65 }
66 "receive-pack" => {
67 body.push_str(&"001f# service=git-receive-pack\n".to_string());
68 body.push_str("0000");
69 }
70 _ => {}
71 }
72 body.push_str(&String::from_utf8(output.stdout).unwrap());
73 Ok(resp.body(body.as_bytes().to_vec()))
74}