Bounded WEB HTTP conveyor with replay-safe streaming downlink added

Co-Authored-By: brekotis <93345790+brekotis@users.noreply.github.com>
This commit is contained in:
Alexey
2026-10-03 16:02:18 +03:00
parent c4555e25f3
commit 823c6cbc7f
39 changed files with 2186 additions and 237 deletions
+4
View File
@@ -72,3 +72,7 @@ mod tests;
#[cfg(test)]
#[path = "hot_reload/carrier_method_tests.rs"]
mod carrier_method_tests;
#[cfg(test)]
#[path = "hot_reload/conveyor_tests.rs"]
mod conveyor_tests;
+20
View File
@@ -0,0 +1,20 @@
use super::*;
#[test]
fn conveyor_reload_is_hot_in_both_directions_and_preserves_process_limits() {
let mut active = ProxyConfig::default();
for enabled in [false, true] {
let mut desired = active.clone();
desired.web.conveyor = enabled;
assert_eq!(classify_config_changes(&active, &desired).changed, ["web"]);
assert!(!classify_config_changes(&active, &desired).restart_required);
desired.web.limits.max_body_readers += 1;
let applied = overlay_hot_fields(&active, &desired);
assert_eq!(applied.web.conveyor, enabled);
assert_eq!(
applied.web.limits.max_body_readers,
active.web.limits.max_body_readers
);
active = applied;
}
}
+1
View File
@@ -264,6 +264,7 @@ const WEB_CONFIG_KEYS: &[&str] = &[
"enabled",
"carrier",
"carrier_method",
"conveyor",
"carriers",
"carrier_learning",
"carrier_negotiation_aggressiveness",
+2 -1
View File
@@ -4,7 +4,8 @@ const WEB_DEBUG_RENDERERS: usize = 2;
const WEB_DEBUG_STATUS_PAGE_BYTES: usize = 8 * 1024 * 1024;
const WEB_DEBUG_GROUP_SCRATCH_BYTES: usize = 4 * 1024 * 1024;
const WEB_CARRIER_LEARNING_ENTRY_BYTES: usize = 512;
const WEB_LANE_STATE_BYTES: usize = 512;
// Includes the lane plus bounded conveyor slots, Notify ownership, and both hash tables.
const WEB_LANE_STATE_BYTES: usize = 1024;
const WEB_OVERLOAD_CONNECTION_BYTES: usize = 4 * 1024;
// Each profile capability is stored in its vhost and in the global containment table.
const WEB_CAPABILITY_INDEX_ENTRY_BYTES: usize = 64;
@@ -7,6 +7,9 @@ mod base_path_tests;
#[path = "web_tests/carrier_method_tests.rs"]
mod carrier_method_tests;
#[path = "web_tests/conveyor_tests.rs"]
mod conveyor_tests;
const WEB_CONFIG: &str = r#"
[access.users]
alice = "000102030405060708090a0b0c0d0e0f"
@@ -0,0 +1,44 @@
use super::*;
#[test]
fn conveyor_defaults_on_and_roundtrips_without_changing_capabilities() {
let default = load_config_from_temp_toml(WEB_CONFIG);
assert!(default.web.conveyor);
assert!(ProxyConfig::default().web.conveyor);
let capabilities = default.web.runtime.as_ref().unwrap().capabilities.clone();
for enabled in [false, true] {
let configured = WEB_CONFIG.replace(
"carrier = \"https-lanes\"",
&format!("carrier = \"https-lanes\"\nconveyor = {enabled}"),
);
let config =
load_config_from_temp_toml(&format!("[general]\nconfig_strict = true\n{configured}",));
assert_eq!(config.web.conveyor, enabled);
assert_eq!(
config.web.runtime.as_ref().unwrap().capabilities,
capabilities
);
let json = serde_json::to_value(&config.web).unwrap();
assert_eq!(json["conveyor"], enabled);
assert_eq!(
serde_json::from_value::<WebConfig>(json).unwrap().conveyor,
enabled
);
let toml = toml::to_string(&config.web).unwrap();
assert_eq!(
toml::from_str::<WebConfig>(&toml).unwrap().conveyor,
enabled
);
}
}
#[test]
fn conveyor_rejects_non_boolean_values() {
for value in ["\"true\"", "1", "0", "[]", "{}"] {
let configured = WEB_CONFIG.replace(
"carrier = \"https-lanes\"",
&format!("carrier = \"https-lanes\"\nconveyor = {value}"),
);
assert!(load_config_error_from_temp_toml(&configured).contains("conveyor"));
}
}
+4
View File
@@ -416,6 +416,9 @@ pub struct WebConfig {
/// Page-owned HTTP method for HTTPS uplink and downlink, including retries.
#[serde(default)]
pub carrier_method: WebCarrierMethod,
/// Enables negotiated bounded HTTP uplink pipelining for new WEB sessions.
#[serde(default = "default_web_conveyor")]
pub conveyor: bool,
/// Ordered carriers considered by server-side negotiation before the fallback carrier.
#[serde(default)]
pub carriers: WebCarriers,
@@ -475,6 +478,7 @@ impl Default for WebConfig {
enabled: false,
carrier: WebCarrier::default(),
carrier_method: WebCarrierMethod::default(),
conveyor: default_web_conveyor(),
carriers: WebCarriers::default(),
carrier_learning: default_web_carrier_learning(),
carrier_negotiation_aggressiveness: WebCarrierNegotiationAggressiveness::default(),
+5
View File
@@ -2,6 +2,11 @@ pub(super) fn default_web_static_index() -> String {
"index.html".to_string()
}
/// Enables explicitly negotiated HTTP pipelining unless the operator disables it.
pub(super) fn default_web_conveyor() -> bool {
true
}
macro_rules! usize_default {
($name:ident, $value:expr) => {
pub(super) fn $name() -> usize {