🏡 index : ~doyle/rgit.git

author Jordan Doyle <jordan@doyle.la> 2024-02-03 14:12:43.0 +00:00:00
committer Jordan Doyle <jordan@doyle.la> 2024-02-03 14:14:05.0 +00:00:00
commit
96928a28c708f08e2c64047ee314d77016a394ce [patch]
tree
9fd2b15e6d671630a4ab66ff27a7a158ed84ce14
parent
460d60799d37e04686c3d0199dd9fc02ff0c9c7a
download
96928a28c708f08e2c64047ee314d77016a394ce.tar.gz

Forward Content-Encoding to git http-backend

Fixes #56

Diff

 src/methods/filters.rs        |  1 +
 src/methods/repo/smart_git.rs | 30 +++++++++++++++++++++++-------
 2 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/src/methods/filters.rs b/src/methods/filters.rs
index b460102..3ee1329 100644
--- a/src/methods/filters.rs
+++ a/src/methods/filters.rs
@@ -1,7 +1,8 @@
// sorry clippy, we don't have a choice. askama forces this on us
#![allow(clippy::unnecessary_wraps, clippy::trivially_copy_pass_by_ref)]

use std::borrow::Borrow;

use time::format_description::well_known::Rfc3339;

pub fn format_time(s: impl Borrow<time::OffsetDateTime>) -> Result<String, askama::Error> {
diff --git a/src/methods/repo/smart_git.rs b/src/methods/repo/smart_git.rs
index 52d8fcb..7d4463c 100644
--- a/src/methods/repo/smart_git.rs
+++ a/src/methods/repo/smart_git.rs
@@ -1,16 +1,17 @@
use std::{io::ErrorKind, path::Path, process::Stdio, str::FromStr};

use anyhow::{bail, Context};
use axum::{
    body::{boxed, Body},
    extract::BodyStream,
    headers::{ContentType, HeaderName, HeaderValue},
    headers::{HeaderMap, HeaderName, HeaderValue},
    http::{Method, Uri},
    response::Response,
    Extension, TypedHeader,
    Extension,
};
use futures::TryStreamExt;
use httparse::Status;
use tokio::process::Command;
use tokio_util::io::StreamReader;
use tracing::warn;

@@ -25,15 +26,20 @@
    Extension(Repository(repository)): Extension<Repository>,
    method: Method,
    uri: Uri,
    content_type: Option<TypedHeader<ContentType>>,
    headers: HeaderMap,
    body: BodyStream,
) -> Result<Response> {
    let path = extract_path(&uri, &repository)?;

    let mut command = tokio::process::Command::new("git");

    if let Some(content_type) = content_type {
        command.env("CONTENT_TYPE", content_type.0.to_string());
    let mut command = Command::new("git");

    for (header, env) in [
        ("Content-Type", "CONTENT_TYPE"),
        ("Content-Length", "CONTENT_LENGTH"),
        ("Git-Protocol", "GIT_PROTOCOL"),
        ("Content-Encoding", "HTTP_CONTENT_ENCODING"),
    ] {
        extract_header(&headers, &mut command, header, env)?;
    }

    let mut child = command
@@ -53,7 +59,7 @@
            StreamReader::new(body.map_err(|e| std::io::Error::new(ErrorKind::Other, e)));
        let mut stdin = child.stdin.take().context("Stdin already taken")?;

        tokio::io::copy(&mut body, &mut stdin)
        tokio::io::copy_buf(&mut body, &mut stdin)
            .await
            .context("Failed to copy bytes from request to command stdin")?;
    }
@@ -72,6 +78,14 @@
    }

    Ok(resp)
}

fn extract_header(input: &HeaderMap, output: &mut Command, header: &str, env: &str) -> Result<()> {
    if let Some(value) = input.get(header) {
        output.env(env, value.to_str().context("Invalid header")?);
    }

    Ok(())
}

fn extract_path<'a>(uri: &'a Uri, repository: &Path) -> Result<&'a str> {