mirror of
https://github.com/nimbold/Firelink.git
synced 2026-08-07 09:53:17 +00:00
fix(download): automatically degrade to single connection when server rejects chunked range bounds
When a server (like fuckingfast.co) ignores the upper bound of a range request (returning bytes=start-end/total), aria2 aborts with 'Invalid range header'. This patch treats that error as transient and mutates the download payload to force connections=1 before re-enqueuing. This ensures aria2 issues an open-ended range request (bytes=start-) on the retry, seamlessly resuming the download.
This commit is contained in:
@@ -492,6 +492,8 @@ impl<R: tauri::Runtime> QueueManager<R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log::error!("aria2 download {} failed: {}", id, error);
|
||||||
|
|
||||||
self.clear_aria2_retry_state(id).await;
|
self.clear_aria2_retry_state(id).await;
|
||||||
self.forget_aria2_gid(id).await;
|
self.forget_aria2_gid(id).await;
|
||||||
self.emit_failed(id, error);
|
self.emit_failed(id, error);
|
||||||
@@ -630,7 +632,13 @@ impl<R: tauri::Runtime> QueueManager<R> {
|
|||||||
.await;
|
.await;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let payload = payload.unwrap();
|
let mut payload = payload.unwrap();
|
||||||
|
|
||||||
|
if error.to_ascii_lowercase().contains("invalid range header") {
|
||||||
|
log::warn!("Server does not support chunked ranges. Degrading {} to single connection.", id);
|
||||||
|
payload.connections = Some(1);
|
||||||
|
self.aria2_payloads.lock().await.insert(id.clone(), payload.clone());
|
||||||
|
}
|
||||||
|
|
||||||
let this = Arc::clone(self);
|
let this = Arc::clone(self);
|
||||||
let stale_gid = gid.to_string();
|
let stale_gid = gid.to_string();
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ pub fn is_transient_network_error(message: &str) -> bool {
|
|||||||
|
|
||||||
let m = message.to_ascii_lowercase();
|
let m = message.to_ascii_lowercase();
|
||||||
|
|
||||||
const TRANSIENT: [&str; 34] = [
|
const TRANSIENT: [&str; 35] = [
|
||||||
// reqwest / hyper / OS socket-layer
|
// reqwest / hyper / OS socket-layer
|
||||||
"timed out",
|
"timed out",
|
||||||
"timeout",
|
"timeout",
|
||||||
@@ -141,6 +141,7 @@ pub fn is_transient_network_error(message: &str) -> bool {
|
|||||||
// aria2c log phrasing
|
// aria2c log phrasing
|
||||||
"connection was closed",
|
"connection was closed",
|
||||||
"timeout.",
|
"timeout.",
|
||||||
|
"invalid range header",
|
||||||
];
|
];
|
||||||
TRANSIENT.iter().any(|t| m.contains(t))
|
TRANSIENT.iter().any(|t| m.contains(t))
|
||||||
}
|
}
|
||||||
@@ -278,6 +279,7 @@ mod tests {
|
|||||||
assert!(is_transient_network_error("network is unreachable"));
|
assert!(is_transient_network_error("network is unreachable"));
|
||||||
assert!(is_transient_network_error("The response status is not successful. status=503"));
|
assert!(is_transient_network_error("The response status is not successful. status=503"));
|
||||||
assert!(is_transient_network_error("The response status is not successful. status=502"));
|
assert!(is_transient_network_error("The response status is not successful. status=502"));
|
||||||
|
assert!(is_transient_network_error("Invalid range header. Request: 106954752-361758719/383882118, Response: 106954752-383882117/383882118"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- transient classification: negative cases -------------------------
|
// --- transient classification: negative cases -------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user