Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
httpd: use `RequestDecompressionLayer` in git handler
Defelo committed 14 days ago
commit 0b89857f21070c475212bd1e760c7098ef695299
parent a4c6f04028c109e281e6f6682a907e466a4d50e0
3 files changed +122 -30
modified radicle-httpd/Cargo.lock
@@ -68,6 +68,21 @@ dependencies = [
]

[[package]]
+
name = "alloc-no-stdlib"
+
version = "2.0.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
+

+
[[package]]
+
name = "alloc-stdlib"
+
version = "0.2.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece"
+
dependencies = [
+
 "alloc-no-stdlib",
+
]
+

+
[[package]]
name = "allocator-api2"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -189,6 +204,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"

[[package]]
+
name = "async-compression"
+
version = "0.4.42"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e79b3f8a79cccc2898f31920fc69f304859b3bd567490f75ebf51ae1c792a9ac"
+
dependencies = [
+
 "compression-codecs",
+
 "compression-core",
+
 "pin-project-lite",
+
 "tokio",
+
]
+

+
[[package]]
name = "autocfg"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -361,6 +388,27 @@ dependencies = [
]

[[package]]
+
name = "brotli"
+
version = "8.0.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560"
+
dependencies = [
+
 "alloc-no-stdlib",
+
 "alloc-stdlib",
+
 "brotli-decompressor",
+
]
+

+
[[package]]
+
name = "brotli-decompressor"
+
version = "5.0.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03"
+
dependencies = [
+
 "alloc-no-stdlib",
+
 "alloc-stdlib",
+
]
+

+
[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -504,6 +552,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"

[[package]]
+
name = "compression-codecs"
+
version = "0.4.38"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "ce2548391e9c1929c21bf6aa2680af86fe4c1b33e6cea9ac1cfeec0bd11218cf"
+
dependencies = [
+
 "brotli",
+
 "compression-core",
+
 "flate2",
+
 "memchr",
+
 "zstd",
+
 "zstd-safe",
+
]
+

+
[[package]]
+
name = "compression-core"
+
version = "0.4.32"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "cc14f565cf027a105f7a44ccf9e5b424348421a1d8952a8fc9d499d313107789"
+

+
[[package]]
name = "console"
version = "0.16.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2324,7 +2392,6 @@ dependencies = [
 "axum-listener",
 "base64 0.22.1",
 "chrono",
-
 "flate2",
 "hyper",
 "infer",
 "lexopt",
@@ -3255,6 +3322,19 @@ dependencies = [
]

[[package]]
+
name = "tokio-util"
+
version = "0.7.18"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098"
+
dependencies = [
+
 "bytes",
+
 "futures-core",
+
 "futures-sink",
+
 "pin-project-lite",
+
 "tokio",
+
]
+

+
[[package]]
name = "tower"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3290,11 +3370,16 @@ version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
dependencies = [
+
 "async-compression",
 "bitflags 2.9.1",
 "bytes",
+
 "futures-core",
 "http",
 "http-body",
+
 "http-body-util",
 "pin-project-lite",
+
 "tokio",
+
 "tokio-util",
 "tower-layer",
 "tower-service",
 "tracing",
@@ -4238,3 +4323,31 @@ name = "zmij"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
+

+
[[package]]
+
name = "zstd"
+
version = "0.13.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a"
+
dependencies = [
+
 "zstd-safe",
+
]
+

+
[[package]]
+
name = "zstd-safe"
+
version = "7.2.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d"
+
dependencies = [
+
 "zstd-sys",
+
]
+

+
[[package]]
+
name = "zstd-sys"
+
version = "2.0.16+zstd.1.5.7"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748"
+
dependencies = [
+
 "cc",
+
 "pkg-config",
+
]
modified radicle-httpd/Cargo.toml
@@ -26,7 +26,6 @@ axum = { version = "0.8.4", default-features = false, features = ["json", "query
axum-listener = { version = "0.2.2" }
base64 = { version = "0.22.1" }
chrono = { version = "0.4.41", default-features = false, features = ["clock"] }
-
flate2 = { version = "1" }
hyper = { version = "1.6.0", default-features = false }
infer = { version = "0.19.0" }
lexopt = { version = "0.3.1" }
@@ -41,7 +40,7 @@ serde = { version = "1", features = ["derive"] }
serde_json = { version = "1", features = ["preserve_order"] }
thiserror = { version = "2" }
tokio = { version = "1.47.1", default-features = false, features = ["macros", "rt-multi-thread", "signal"] }
-
tower-http = { version = "0.6.6", default-features = false, features = ["trace", "cors", "set-header"] }
+
tower-http = { version = "0.6.6", default-features = false, features = ["trace", "cors", "set-header", "decompression-full"] }
tracing = { version = "0.1.41", default-features = false, features = ["std", "log"] }
tracing-logfmt = { version = "0.3.5", optional = true }
tracing-subscriber = { version = "0.3.19", default-features = false, features = ["std", "ansi", "fmt"] }
modified radicle-httpd/src/git.rs
@@ -13,19 +13,21 @@ use axum::response::IntoResponse;
use axum::routing::any;
use axum::Router;
use axum_listener::DualAddr;
-
use flate2::write::GzDecoder;
-
use hyper::body::Buf as _;

use radicle::identity::RepoId;
use radicle::node::NodeId;
use radicle::profile::Profile;
use radicle::storage::{ReadRepository, ReadStorage};
+
use tower_http::decompression::RequestDecompressionLayer;

use crate::error::GitError as Error;

pub fn router(profile: Arc<Profile>, aliases: HashMap<String, RepoId>) -> Router {
    Router::new()
-
        .route("/{rid}/{*request}", any(git_handler))
+
        .route(
+
            "/{rid}/{*request}",
+
            any(git_handler).layer(RequestDecompressionLayer::new()),
+
        )
        .with_state((profile, aliases))
}

@@ -78,7 +80,7 @@ async fn git_http_backend(
    profile: &Profile,
    method: Method,
    headers: HeaderMap,
-
    mut body: Bytes,
+
    body: Bytes,
    remote: DualAddr,
    id: RepoId,
    nid: Option<NodeId>,
@@ -137,32 +139,10 @@ async fn git_http_backend(
        .stdin(Stdio::piped())
        .spawn()?;

-
    // Whether the request body is compressed.
-
    let gzip = matches!(
-
        headers.get("Content-Encoding").map(|h| h.to_str()),
-
        Some(Ok("gzip"))
-
    );
-

    {
        // This is safe because we captured the child's stdin.
        let mut stdin = child.stdin.take().unwrap();
-

-
        // Copy the request body to git-http-backend's stdin.
-
        if gzip {
-
            let mut decoder = GzDecoder::new(&mut stdin);
-
            let mut reader = body.reader();
-

-
            io::copy(&mut reader, &mut decoder)?;
-
            decoder.finish()?;
-
        } else {
-
            while body.has_remaining() {
-
                let mut chunk = body.chunk();
-
                let count = chunk.len();
-

-
                io::copy(&mut chunk, &mut stdin)?;
-
                body.advance(count);
-
            }
-
        }
+
        stdin.write_all(&body)?;
    }

    match child.wait_with_output() {