Skip to content

Commit 5859649

Browse files
author
share121
committed
feat: 处理 Retry-After 头
1 parent d8767b0 commit 5859649

File tree

3 files changed

+29
-31
lines changed

3 files changed

+29
-31
lines changed

Cargo.lock

Lines changed: 1 addition & 27 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/fast-down/Cargo.toml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,18 @@ reqwest = { version = "0.12.22", default-features = false, features = [
2424
], optional = true }
2525
kanal.workspace = true
2626
log = "0.4.27"
27-
reqwest-middleware = { version = "0.4.2", optional = true }
2827
thiserror.workspace = true
28+
tokio = { version = "1.47.1", default-features = false }
29+
httpdate = { version = "1.0.3", optional = true }
2930

3031
[features]
31-
default = ["reqwest-middleware"]
32-
reqwest = ["dep:reqwest", "dep:content_disposition", "dep:urlencoding"]
33-
reqwest-middleware = ["reqwest", "dep:reqwest-middleware"]
32+
default = ["reqwest"]
33+
reqwest = [
34+
"dep:reqwest",
35+
"dep:content_disposition",
36+
"dep:urlencoding",
37+
"dep:httpdate",
38+
]
3439

3540
[dev-dependencies]
3641
tokio = { version = "1.47.1", features = [

crates/fast-down/src/reqwest/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use crate::http::{HttpClient, HttpHeaders, HttpRequestBuilder, HttpResponse};
22
use fast_pull::ProgressEntry;
3+
use httpdate::parse_http_date;
34
use reqwest::{
45
Client, RequestBuilder, Response,
56
header::{self, HeaderMap, HeaderName, InvalidHeaderName},
67
};
8+
use std::time::{Duration, SystemTime};
79
use url::Url;
810

911
impl HttpClient for Client {
@@ -25,6 +27,23 @@ impl HttpRequestBuilder for RequestBuilder {
2527
type RequestError = reqwest::Error;
2628
async fn send(self) -> Result<Self::Response, Self::RequestError> {
2729
let res = self.send().await?;
30+
let retry_after = res.headers().get(header::RETRY_AFTER);
31+
if let Some(retry_after) = retry_after
32+
&& let Ok(retry_after) = retry_after.to_str()
33+
{
34+
let retry_after = match retry_after.parse() {
35+
Ok(retry_after) => Some(Duration::from_secs(retry_after)),
36+
Err(_) => match parse_http_date(retry_after) {
37+
Ok(target_time) => target_time.duration_since(SystemTime::now()).ok(),
38+
Err(_) => None,
39+
},
40+
};
41+
if let Some(retry_after) = retry_after
42+
&& retry_after > Duration::ZERO
43+
{
44+
tokio::time::sleep(retry_after).await;
45+
}
46+
}
2847
res.error_for_status()
2948
}
3049
}

0 commit comments

Comments
 (0)