git_http_backend/actix/
objects_pack.rs

1use crate::GitConfig;
2use actix_files::NamedFile;
3use actix_web::cookie::time;
4use actix_web::cookie::time::format_description;
5use actix_web::http::header;
6use actix_web::http::header::HeaderValue;
7use actix_web::{web, HttpRequest, HttpResponse, Responder};
8use std::collections::HashMap;
9
10pub async fn objects_pack(
11    request: HttpRequest,
12    service: web::Data<impl GitConfig>,
13) -> impl Responder {
14    let uri = request.uri();
15    let path = uri.path().to_string();
16    let req_file = service.rewrite(path).await;
17    let mut map = HashMap::new();
18    let time = time::OffsetDateTime::now_utc();
19    let expires = time::OffsetDateTime::now_utc() + time::Duration::days(1);
20    map.insert(
21        "Date".to_string(),
22        time.format(&format_description::parse("%a, %d %b %Y %H:%M:%S GMT").unwrap())
23            .unwrap(),
24    );
25    map.insert(
26        "Expires".to_string(),
27        expires
28            .format(&format_description::parse("%a, %d %b %Y %H:%M:%S GMT").unwrap())
29            .unwrap(),
30    );
31    map.insert(
32        "Cache-Control".to_string(),
33        "public, max-age=86400".to_string(),
34    );
35    #[allow(unused_assignments)]
36    let mut xtype = "application/x-git-loose-object".to_string();
37    if uri.to_string().ends_with(".pack") {
38        xtype = "application/x-git-packed-objects".to_string();
39    } else if uri.to_string().ends_with(".idx") {
40        xtype = "application/x-git-packed-objects-toc".to_string();
41    } else {
42        xtype = "application/x-git-loose-object".to_string();
43    }
44    if !req_file.exists() {
45        return HttpResponse::NotFound().body("File not found");
46    }
47    match NamedFile::open(req_file) {
48        Ok(mut named_file) => {
49            named_file = named_file.use_last_modified(true);
50            let mut response = named_file.into_response(&request);
51            for (k, v) in map.iter() {
52                response.headers_mut().insert(
53                    k.to_string().parse().unwrap(),
54                    HeaderValue::from_str(v).unwrap(),
55                );
56            }
57
58            response
59                .headers_mut()
60                .insert(header::CONTENT_TYPE, HeaderValue::from_str(&xtype).unwrap());
61            response
62        }
63        Err(_) => HttpResponse::InternalServerError().body("Failed to open file"),
64    }
65}