Compare commits

..

5 commits

6 changed files with 2381 additions and 1382 deletions

1204
Cargo.lock generated

File diff suppressed because it is too large Load diff

2405
Cargo.nix

File diff suppressed because it is too large Load diff

84
flake.lock generated
View file

@ -10,17 +10,17 @@
"rust-overlay": "rust-overlay"
},
"locked": {
"lastModified": 1666087781,
"narHash": "sha256-trKVdjMZ8mNkGfLcY5LsJJGtdV3xJDZnMVrkFjErlcs=",
"owner": "Alexis211",
"lastModified": 1713199118,
"narHash": "sha256-MlLdAvk+zXCFUy280sY6LqtykqWXIkKVXo72J7a6HlU=",
"owner": "cargo2nix",
"repo": "cargo2nix",
"rev": "a7a61179b66054904ef6a195d8da736eaaa06c36",
"rev": "1efb03f2f794ad5eed17e807e858c4da001dbc3e",
"type": "github"
},
"original": {
"owner": "Alexis211",
"owner": "cargo2nix",
"repo": "cargo2nix",
"rev": "a7a61179b66054904ef6a195d8da736eaaa06c36",
"rev": "1efb03f2f794ad5eed17e807e858c4da001dbc3e",
"type": "github"
}
},
@ -55,93 +55,47 @@
"type": "github"
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1694529238,
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1696234590,
"narHash": "sha256-mgOzQYTvaTT4bFopVOadlndy2RPwLy60rDjIWOGujwo=",
"lastModified": 1731094700,
"narHash": "sha256-lSiVjHP7sgnCt2hZabnq+tCLmBerDKmAdd2CS6BrBjw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "f902cb49892d300ff15cb237e48aa1cad79d68c3",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1665657542,
"narHash": "sha256-mojxNyzbvmp8NtVtxqiHGhRfjCALLfk9i/Uup68Y5q8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a3073c49bc0163fea6a121c276f526837672b555",
"rev": "551ba0fa7653afb9d590db225c3bcbccf68931c0",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a3073c49bc0163fea6a121c276f526837672b555",
"rev": "551ba0fa7653afb9d590db225c3bcbccf68931c0",
"type": "github"
}
},
"root": {
"inputs": {
"cargo2nix": "cargo2nix",
"nixpkgs": "nixpkgs_2"
"nixpkgs": "nixpkgs"
}
},
"rust-overlay": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs"
"nixpkgs": [
"cargo2nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1682389182,
"narHash": "sha256-8t2nmFnH+8V48+IJsf8AK51ebXNlVbOSVYOpiqJKvJE=",
"lastModified": 1731032894,
"narHash": "sha256-dQSyYPmrQiPr+PGEd+K8038rubFGz7G/dNXVeaGWE0w=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "74f1a64dd28faeeb85ef081f32cad2989850322c",
"rev": "d52f2a4c103a0acf09ded857b9e2519ae2360e59",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"rev": "d52f2a4c103a0acf09ded857b9e2519ae2360e59",
"type": "github"
}
}

View file

@ -1,31 +1,43 @@
{
description = "A very basic flake";
description = "Tricot, a reverse proxy with consul integration";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/a3073c49bc0163fea6a121c276f526837672b555";
# Nixpkgs 24.05 as of 2024-11-08, has rustc v1.77.2
inputs.nixpkgs.url =
"github:NixOS/nixpkgs/551ba0fa7653afb9d590db225c3bcbccf68931c0";
inputs.cargo2nix = {
# As of 2022-10-18: two small patches over unstable branch, one for clippy and one to fix feature detection
url = "github:Alexis211/cargo2nix/a7a61179b66054904ef6a195d8da736eaaa06c36";
# cargo2nix as of 2024-04-25
# NB: upgrading to a more recent commit of cargo2nix will not work (as of 2024-11-08),
# because the patch making openssl-sys cross-compilation work has been reverted.
# (patch: https://github.com/cargo2nix/cargo2nix/pull/237,
# revert: https://github.com/cargo2nix/cargo2nix/commit/cfd086deb565314f3a11b5bb25807a3ce17315d4)
url = "github:cargo2nix/cargo2nix/1efb03f2f794ad5eed17e807e858c4da001dbc3e";
# Rust overlay as of 2023-04-25
# Rust overlay as of 2024-11-08
inputs.rust-overlay.url =
"github:oxalica/rust-overlay/74f1a64dd28faeeb85ef081f32cad2989850322c";
"github:oxalica/rust-overlay/d52f2a4c103a0acf09ded857b9e2519ae2360e59";
inputs.nixpkgs.follows = "nixpkgs";
};
outputs = { self, nixpkgs, cargo2nix }:
let
targetHost = "x86_64-unknown-linux-musl";
pkgs = import nixpkgs {
system = "x86_64-linux";
crossSystem = {
config = targetHost;
isStatic = true;
};
overlays = [ cargo2nix.overlays.default ];
};
packageFun = import ./Cargo.nix;
rustVersion = "1.68.0";
rustVersion = "1.77.2";
compile = args: compileMode:
let
packageSet = pkgs.rustBuilder.makePackageSet ({
inherit packageFun rustVersion;
target = targetHost;
} // args);
in
packageSet.workspace.tricot {
@ -37,5 +49,13 @@
debug.x86_64-linux.tricot = compile { release = false; } "build";
packages.x86_64-linux.tricot = compile { release = true; } "build";
packages.x86_64-linux.default = self.packages.x86_64-linux.tricot;
docker = pkgs.dockerTools.buildImage {
name = "tricot";
config = {
contents = [ pkgs.cacert ];
Cmd = [ "${self.packages.x86_64-linux.default}/bin/tricot" ];
};
};
};
}

View file

@ -41,21 +41,9 @@ pub struct HttpsConfig {
struct HttpsMetrics {
requests_received: metrics::Counter<u64>,
requests_served: metrics::Counter<u64>,
requests_in_flight: metrics::UpDownCounter<i64>,
request_proxy_duration: metrics::Histogram<f64>,
}
struct InFlightGuard<'a, 'b> {
metrics: &'a HttpsMetrics,
tags: &'b [KeyValue],
}
impl<'a, 'b> Drop for InFlightGuard<'a, 'b> {
fn drop(&mut self) {
self.metrics.requests_in_flight.add(-1, self.tags)
}
}
pub async fn serve_https(
config: HttpsConfig,
cert_store: Arc<CertStore>,
@ -74,10 +62,6 @@ pub async fn serve_https(
.u64_counter("https_requests_served")
.with_description("Total number of requests served over HTTPS")
.init(),
requests_in_flight: meter
.i64_up_down_counter("https_requests_in_flight")
.with_description("Current number of requests handled over HTTPS")
.init(),
request_proxy_duration: meter
.f64_histogram("https_request_proxy_duration")
.with_description("Duration between time when request was received, and time when backend returned status code and headers")
@ -194,7 +178,9 @@ async fn handle_request(
.unwrap_or_default(),
);
metrics.requests_received.add(1, &[host_tag, method_tag.clone()]);
metrics
.requests_received
.add(1, &[host_tag, method_tag.clone()]);
let mut tags = vec![method_tag];
let resp = select_target_and_proxy(
@ -286,17 +272,6 @@ async fn select_target_and_proxy(
);
proxy_to.calls_in_progress.fetch_add(1, Ordering::SeqCst);
let tags_in_flight = &tags.clone();
metrics.requests_in_flight.add(1, &tags_in_flight);
// The guard ensures that we decrement requests_in_flight in all cases where
// the current tasks ends, including the case where it gets canceled and
// doesn't run to completion (which may happen e.g. if it timeouts).
// (Crucially we create the guard before the first .await in this function.)
let _guard = InFlightGuard {
metrics: &metrics,
tags: &tags_in_flight,
};
// Forward to backend
debug!("{}{} -> {}", host, path, proxy_to);
trace!("Request: {:?}", req);
@ -396,8 +371,8 @@ async fn do_proxy(
reverse_proxy::call(remote_addr.ip(), &to_addr, req).await?
};
if response.status().is_success() {
// (TODO: maybe we want to add these headers even if it's not a success?)
if response.status().is_success() || response.status().is_redirection() {
// (TODO: maybe we want to add these headers even if it's not a success or redirection?)
for (header, value) in proxy_to.add_headers.iter() {
response.headers_mut().insert(
HeaderName::from_bytes(header.as_bytes())?,

View file

@ -132,6 +132,7 @@ async fn main() {
let opt = Opt::from_args();
info!("Starting Tricot");
println!("Starting Tricot");
let (exit_signal, provoke_exit) = watch_ctrl_c();
let exit_on_err = move |err: anyhow::Error| {