refactor(fetch): share HTTP redirect hop state updates

Commit Referer reduction, method/body rewriting, Cookie context advancement,
current URL, origin key and redirect count through one runtime helper.
Retain Request.url as the initial URL. Each transport still owns response
collection, caching and cancellation, while HTTPS upgrades stay separate.
This commit is contained in:
ldm0
2026-11-12 03:10:33 +08:00
committed by Donough Liu
parent 15a2aa1775
commit dae236828a
+143 -146
View File
@@ -1673,41 +1673,36 @@ impl RuntimeOwner {
if let Some(next_url) = next_url
&& job.request.transport_follows_redirects()
{
job.request
.update_referrer_for_redirect(&response.final_url, &response.headers);
let redirect_has_extra_info = request_extra_info.is_some() && !response.from_cache;
job.request.redirect_chain.push(RedirectInfo {
source: crate::RedirectSource::Network,
from_url: response.final_url.clone(),
to_url: next_url.clone(),
status: response.status,
headers: response.headers.clone(),
network_extra_info_available: redirect_has_extra_info,
request_extra_info: None,
response_extra_info: request_extra_info.map(|request_extra_info| {
network_response_extra_info(
request_extra_info,
response.status,
response.headers.clone(),
response.cookie_set_reports.clone(),
)
}),
redirect_has_extra_info,
request_cookie_report: None,
cookie_set_reports: response.cookie_set_reports.clone(),
from_cache: response.from_cache,
negotiated_http_version: response.negotiated_http_version,
});
job.request.apply_redirect_status(response.status);
job.current_cookie_context = advance_cookie_request_context(
job.current_cookie_context = commit_redirect_hop(
&mut job.request,
job.current_cookie_context,
&job.request.url,
&next_url,
&job.request.method,
&mut job.current_url,
&mut job.origin_key,
&mut job.redirect_count,
RedirectInfo {
source: crate::RedirectSource::Network,
from_url: response.final_url.clone(),
to_url: next_url,
status: response.status,
headers: response.headers.clone(),
network_extra_info_available: redirect_has_extra_info,
request_extra_info: None,
response_extra_info: request_extra_info.map(|request_extra_info| {
network_response_extra_info(
request_extra_info,
response.status,
response.headers.clone(),
response.cookie_set_reports.clone(),
)
}),
redirect_has_extra_info,
request_cookie_report: None,
cookie_set_reports: response.cookie_set_reports.clone(),
from_cache: response.from_cache,
negotiated_http_version: response.negotiated_http_version,
},
);
job.current_url = next_url;
job.origin_key = origin_key_for_url(&job.current_url);
job.redirect_count += 1;
job.http_version = RequestHttpVersion::PreferHttp2;
return Ok(JobOutcome::Retry(Box::new(job)));
}
@@ -1979,41 +1974,36 @@ impl RuntimeOwner {
{
tracing::debug!(url = %job.current_url, "failed to store streaming redirect response in disk cache: {error}");
}
job.request
.update_referrer_for_redirect(&final_url, &headers);
let redirect_has_extra_info = request_extra_info.is_some();
job.request.redirect_chain.push(RedirectInfo {
source: crate::RedirectSource::Network,
from_url: final_url,
to_url: next_url.clone(),
status,
headers: headers.clone(),
network_extra_info_available: redirect_has_extra_info,
request_extra_info: None,
response_extra_info: request_extra_info.map(|request_extra_info| {
network_response_extra_info(
request_extra_info,
status,
headers,
cookie_set_reports.clone(),
)
}),
redirect_has_extra_info,
request_cookie_report,
cookie_set_reports,
from_cache: false,
negotiated_http_version,
});
job.request.apply_redirect_status(status);
job.current_cookie_context = advance_cookie_request_context(
job.current_cookie_context = commit_redirect_hop(
&mut job.request,
job.current_cookie_context,
&job.request.url,
&next_url,
&job.request.method,
&mut job.current_url,
&mut job.origin_key,
&mut job.redirect_count,
RedirectInfo {
source: crate::RedirectSource::Network,
from_url: final_url,
to_url: next_url,
status,
headers: headers.clone(),
network_extra_info_available: redirect_has_extra_info,
request_extra_info: None,
response_extra_info: request_extra_info.map(|request_extra_info| {
network_response_extra_info(
request_extra_info,
status,
headers,
cookie_set_reports.clone(),
)
}),
redirect_has_extra_info,
request_cookie_report,
cookie_set_reports,
from_cache: false,
negotiated_http_version,
},
);
job.current_url = next_url;
job.origin_key = origin_key_for_url(&job.current_url);
job.redirect_count += 1;
job.http_version = RequestHttpVersion::PreferHttp2;
job.easy = Some(easy);
self.start_streaming_job_or_reply(state, job);
@@ -2377,41 +2367,36 @@ impl RuntimeOwner {
{
tracing::debug!(url = %job.current_url, "failed to store raw streaming redirect response in disk cache: {error}");
}
job.request
.update_referrer_for_redirect(&final_url, &headers);
let redirect_has_extra_info = request_extra_info.is_some();
job.request.redirect_chain.push(RedirectInfo {
source: crate::RedirectSource::Network,
from_url: final_url,
to_url: next_url.clone(),
status,
headers: headers.clone(),
network_extra_info_available: redirect_has_extra_info,
request_extra_info: None,
response_extra_info: request_extra_info.map(|request_extra_info| {
network_response_extra_info(
request_extra_info,
status,
headers,
cookie_set_reports.clone(),
)
}),
redirect_has_extra_info,
request_cookie_report,
cookie_set_reports,
from_cache: false,
negotiated_http_version,
});
job.request.apply_redirect_status(status);
job.current_cookie_context = advance_cookie_request_context(
job.current_cookie_context = commit_redirect_hop(
&mut job.request,
job.current_cookie_context,
&job.request.url,
&next_url,
&job.request.method,
&mut job.current_url,
&mut job.origin_key,
&mut job.redirect_count,
RedirectInfo {
source: crate::RedirectSource::Network,
from_url: final_url,
to_url: next_url,
status,
headers: headers.clone(),
network_extra_info_available: redirect_has_extra_info,
request_extra_info: None,
response_extra_info: request_extra_info.map(|request_extra_info| {
network_response_extra_info(
request_extra_info,
status,
headers,
cookie_set_reports.clone(),
)
}),
redirect_has_extra_info,
request_cookie_report,
cookie_set_reports,
from_cache: false,
negotiated_http_version,
},
);
job.current_url = next_url;
job.origin_key = origin_key_for_url(&job.current_url);
job.redirect_count += 1;
job.http_version = RequestHttpVersion::PreferHttp2;
job.easy = Some(easy);
self.start_raw_streaming_job_or_reply(state, job);
@@ -2522,33 +2507,28 @@ impl RuntimeOwner {
if let Some(next_url) = next_url
&& job.request.transport_follows_redirects()
{
job.request
.update_referrer_for_redirect(&final_url, &cached.headers);
job.request.redirect_chain.push(RedirectInfo {
source: crate::RedirectSource::Network,
from_url: final_url,
to_url: next_url.clone(),
status: cached.status,
headers: cached.headers,
network_extra_info_available: false,
request_extra_info: None,
response_extra_info: None,
redirect_has_extra_info: false,
request_cookie_report,
cookie_set_reports: Vec::new(),
from_cache: true,
negotiated_http_version: None,
});
job.request.apply_redirect_status(cached.status);
job.current_cookie_context = advance_cookie_request_context(
job.current_cookie_context = commit_redirect_hop(
&mut job.request,
job.current_cookie_context,
&job.request.url,
&next_url,
&job.request.method,
&mut job.current_url,
&mut job.origin_key,
&mut job.redirect_count,
RedirectInfo {
source: crate::RedirectSource::Network,
from_url: final_url,
to_url: next_url,
status: cached.status,
headers: cached.headers,
network_extra_info_available: false,
request_extra_info: None,
response_extra_info: None,
redirect_has_extra_info: false,
request_cookie_report,
cookie_set_reports: Vec::new(),
from_cache: true,
negotiated_http_version: None,
},
);
job.current_url = next_url;
job.origin_key = origin_key_for_url(&job.current_url);
job.redirect_count += 1;
job.http_version = RequestHttpVersion::PreferHttp2;
self.start_streaming_job_or_reply(state, job);
return Ok(());
@@ -2587,33 +2567,28 @@ impl RuntimeOwner {
if let Some(next_url) = next_url
&& job.request.transport_follows_redirects()
{
job.request
.update_referrer_for_redirect(&final_url, &cached.headers);
job.request.redirect_chain.push(RedirectInfo {
source: crate::RedirectSource::Network,
from_url: final_url,
to_url: next_url.clone(),
status: cached.status,
headers: cached.headers,
network_extra_info_available: false,
request_extra_info: None,
response_extra_info: None,
redirect_has_extra_info: false,
request_cookie_report,
cookie_set_reports: Vec::new(),
from_cache: true,
negotiated_http_version: None,
});
job.request.apply_redirect_status(cached.status);
job.current_cookie_context = advance_cookie_request_context(
job.current_cookie_context = commit_redirect_hop(
&mut job.request,
job.current_cookie_context,
&job.request.url,
&next_url,
&job.request.method,
&mut job.current_url,
&mut job.origin_key,
&mut job.redirect_count,
RedirectInfo {
source: crate::RedirectSource::Network,
from_url: final_url,
to_url: next_url,
status: cached.status,
headers: cached.headers,
network_extra_info_available: false,
request_extra_info: None,
response_extra_info: None,
redirect_has_extra_info: false,
request_cookie_report,
cookie_set_reports: Vec::new(),
from_cache: true,
negotiated_http_version: None,
},
);
job.current_url = next_url;
job.origin_key = origin_key_for_url(&job.current_url);
job.redirect_count += 1;
job.http_version = RequestHttpVersion::PreferHttp2;
self.start_raw_streaming_job_or_reply(state, job);
return Ok(());
@@ -2630,6 +2605,28 @@ struct OwnerState {
active_transfers: usize,
}
/// Commit the shared HTTP-hop state while retaining Request.url as the initial URL.
/// Body collection, cache storage and transport retries remain with their owners.
fn commit_redirect_hop(
request: &mut Request,
cookie_context: NetworkCookieRequestContext,
current_url: &mut Url,
origin_key: &mut Option<CurlOriginKey>,
redirect_count: &mut usize,
redirect: RedirectInfo,
) -> NetworkCookieRequestContext {
request.update_referrer_for_redirect(&redirect.from_url, &redirect.headers);
request.apply_redirect_status(redirect.status);
let next_url = redirect.to_url.clone();
let context =
advance_cookie_request_context(cookie_context, &request.url, &next_url, &request.method);
request.record_redirect(redirect);
*current_url = next_url;
*origin_key = origin_key_for_url(current_url);
*redirect_count += 1;
context
}
#[derive(Debug)]
struct RuntimeJob {
request: Request,