Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/gunnar

crates/gunnar-http/Cargo.toml

[package]
name = "gunnar-http"
description = "The git smart-HTTP transport, wrapping gunnar-wire's state machines"
readme = "README.md"
# 1.5.1 (2026-10-26, lane GUN-INSTALL / G-BOTH, the R5C publish): master differs from crates.io, so
# it gets its own version; a patch: cargo-semver-checks finds no API change against crates.io 1.5.0.
version = "2.0.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
# On the `cargo install gunnar` chain (owner order 2026-10-22).
publish = true
authors.workspace = true
repository.workspace = true

[dependencies]
# The seam, the authorisation decision and the service table, shared with SSH
# rather than restated (one implementation). See `gunnar_ssh::seam::Delivery` for why this
# edge costs nothing in any build that has HTTP.
gunnar-ssh.workspace = true
gunnar-core.workspace = true
# `ProtocolVersion::from_git_protocol`: the `Git-Protocol` header carries
# exactly the value the SSH environment variable does, so it is parsed by the
# same grammar and not by a second one.
gunnar-wire.workspace = true
gunnar-pktline.workspace = true
# The LFS batch API's decision, its oid, its quota and its upload verifier —
# the same ones the pure-SSH transfer uses, so an object admitted over HTTP is
# admitted on the terms an object over SSH is (one implementation). No `fs` feature: this
# crate is handed a `dyn LfsStore` through the seam and never opens one.
gunnar-lfs.workspace = true

# hyper 1 + hyper-util, and NOT a framework. Both are already resolved into the
# appliance graph by tonic (gRPC is HTTP/2), so this transport adds no crate to
# any build; measured with `cargo tree -e normal` on 2026-08-03 and asserted by
# `xtask`'s dependency guard. `default-features = false` throughout.
hyper = { version = "1", default-features = false, features = ["server", "http1", "http2"] }
hyper-util = { version = "0.1", default-features = false, features = [
    "server",
    "server-auto",
    "tokio",
] }
# Native TLS for the single-executable deployment shape: the same arrangement
# holger's gateway runs (rustls on ring, ALPN h2 + http/1.1, a TlsAcceptor per
# connection). `ring` and not `aws-lc-rs`, because aws-lc-rs builds C through
# cmake and the workspace rule forbids growing the C surface for a job a
# ring-backed rustls already does; holger made the same choice for the same
# reason. TLS is opt-in per listener: without `HttpConfig::tls` nothing here
# initialises and the proxy-terminated shape is unchanged.
rustls = { version = "0.23", default-features = false, features = ["ring", "std"] }
tokio-rustls = { version = "0.26", default-features = false, features = ["ring"] }
# PEM in, DER out — out of the crate **rustls already depends on**, so the
# smart-HTTP feature adds no package to the appliance image. `rustls-pemfile`
# did the same job and was the single third-party crate `--features http` cost
# (smart HTTP's `appliance-growth` guard, 309 → 310).
#
# `pem` is not a feature: PEM decoding is unconditional in this crate from 1.15
# on, and asking for it by name is a resolution error rather than a no-op. Only
# `std` is named, for `PemObject`'s reader-based arms and the `io::Error`s they
# return.
rustls-pki-types = { version = "1", default-features = false, features = ["std"] }
http-body-util = { version = "0.1", default-features = false }
http-body = { version = "1", default-features = false }
http = { version = "1", default-features = false }
bytes = { version = "1", default-features = false, features = ["std"] }
base64 = { version = "0.23", default-features = false, features = ["std"] }
# git gzips a large POST body (`Content-Encoding: gzip`). Already the zlib the
# whole server runs on; see the workspace manifest for the zlib-rs backend.
flate2.workspace = true
# The LFS batch API is JSON, and both are ALREADY in the appliance graph —
# tonic's reflection and gunnar's own config pull them in — so this surface
# costs the appliance no third-party crate. Asserted, not asserted-in-a-comment:
# `xtask`'s `check_appliance_growth` subtracts the two resolved graphs.
serde.workspace = true
serde_json.workspace = true

tokio.workspace = true
tokio-util.workspace = true
thiserror.workspace = true
tracing.workspace = true

[dev-dependencies]
# PATH-ONLY, no version, and that is load-bearing (2026-08-05). This is the
# only edge from gunnar-http to gunnar-store: there is no normal dependency
# behind it, so nothing forces gunnar-store to publish first. A dev-dependency
# that carries a version must resolve from the REGISTRY at `cargo package`
# time (PROVEN both ways: with a version, `no matching package named ...`;
# without one, cargo strips the entry and packages clean), so the versioned
# form makes this crate publishable only in an order no manifest states.
# `dwarves workspace-release` computes its waves from normal dependencies and
# cannot see this edge at all. Path-only is the by-construction fix: the
# published crate does not name it, and no wave order can be wrong about it.
gunnar-store = { path = "../gunnar-store" }
# `tests/admission.rs` drives the admission gate through a real bound
# listener with a raw HTTP client, so it needs `net` (the client socket) and
# `io-util` (read/write) on top of the runtime.
tokio = { workspace = true, features = ["rt-multi-thread", "macros", "time", "net", "io-util"] }