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(-)
@@ -1,7 +1,8 @@
#![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> {
@@ -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> {