v0.34.0_7

This commit is contained in:
Mateusz Gruszczyński committed 2026-10-18 07:48:59 +02:00
1 parent 47ce1f18c2
commit b6a3e12225
21 files changed
+471 -84

No files matched your search

+2 -1
View File
@@ -193,13 +193,14 @@ async fn forward_request(
}
}
}
let mut context = match snapshot.forwarding.context(
let mut context = match snapshot.forwarding.context_with_original_url(
request.headers(),
peer.0,
local.0,
tls,
&original_host,
request.uri(),
frontend.is_some_and(|frontend| frontend.tinyauth.is_some()),
) {
Ok(context) => context,
Err(_) => {
+9 -10
View File
@@ -1,14 +1,13 @@
fn request_id_hash(sequence: u64) -> String {
use sha2::{Digest, Sha256};
// Thread-local CSPRNG is seeded (and periodically reseeded) from the OS.
// Do not make a getrandom syscall on the hot path for every HTTP request.
// Keep hashing the per-process sequence as before for the same ID format.
let nonce: [u8; 32] = rand::random();
let mut hash = Sha256::new();
hash.update(sequence.to_be_bytes());
hash.update(nonce);
request_id_hex(&hash.finalize())
// Same thread-local CSPRNG as before, now with no per-request SHA-256.
// XORing an increasing sequence into independent uniformly random bytes
// preserves the full 256-bit unpredictability and 64-hex-character shape.
// The sequence is still mixed in; this is not a predictable counter ID.
let mut token: [u8; 32] = rand::random();
for (byte, sequence_byte) in token[..8].iter_mut().zip(sequence.to_be_bytes()) {
*byte ^= sequence_byte;
}
request_id_hex(&token)
}
fn request_id_hex(digest: &[u8]) -> String {
+9
View File
@@ -30,6 +30,15 @@ mod request_id_tests {
}
}
#[test]
fn independent_sequential_ids_keep_full_length_and_unique_values() {
let ids: std::collections::HashSet<_> = (0..4096u64)
.map(request_id_hash)
.collect();
assert_eq!(ids.len(), 4096);
assert!(ids.iter().all(|id| id.len() == 64));
}
#[test]
#[ignore = "explicit release-mode microbenchmark; not an acceptance threshold"]
fn benchmark_request_id_formatting() {
+19 -11
View File
@@ -312,21 +312,29 @@ async fn observe(State(state): State<Arc<App>>, mut request: Request, next: Next
response.headers_mut().remove("alt-svc");
}
let global_compression = &snapshot.envelope.config.compression;
let mut compression = global_compression.clone();
if let Some(frontend) = frontend_context.as_ref() {
compression = frontend
.compression
.resolve(global_compression, &compression);
}
if let Some(route) = effective_route_context {
if let crate::config::CompiledSource::WebServer(service) = &route.source {
compression = service
// All scoped policies have the global codec ceiling. With no accepted
// global encoding (e.g. Accept-Encoding: identity), encode is a no-op:
// avoid even constructing/resolving the per-request settings.
if method != Method::HEAD
&& crate::compression::preferred_encoding(&original_headers, global_compression).is_some()
{
let mut compression = global_compression.clone();
if let Some(frontend) = frontend_context.as_ref() {
compression = frontend
.compression
.resolve(global_compression, &compression);
}
if let Some(route) = effective_route_context {
if let crate::config::CompiledSource::WebServer(service) = &route.source {
compression = service
.compression
.resolve(global_compression, &compression);
}
}
response = crate::compression::encode(
response, &original_headers, &method, &compression,
).await;
}
response =
crate::compression::encode(response, &original_headers, &method, &compression).await;
if let Some(encoding) = response
.extensions()
.get::<crate::compression::AppliedEncoding>()