git_http_backend/actix/
objects_pack.rs1use 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}