diff --git a/src/net/http.rs b/src/net/http.rs index dd516b3350..632a36fd82 100644 --- a/src/net/http.rs +++ b/src/net/http.rs @@ -105,9 +105,9 @@ pub async fn read_url_blob(context: &Context, url: &str) -> Result { .body(http_body_util::Empty::::new())?; let response = sender.send_request(req).await?; - let headers = response.headers(); if response.status().is_redirection() { - let header = headers + let header = response + .headers() .get_all("location") .iter() .last() @@ -226,27 +226,47 @@ pub(crate) async fn get_client(context: &Context, load_cache: bool) -> Result Result<(String, bool)> { - let parsed_url = url - .parse::() - .with_context(|| format!("Failed to parse URL {url:?}"))?; - let scheme = parsed_url.scheme_str().context("URL has no scheme")?; - if scheme != "https" { - bail!("POST requests to non-HTTPS URLs are not allowed"); + let mut url = url.to_string(); + + for _i in 0..10 { + let parsed_url = url + .parse::() + .with_context(|| format!("Failed to parse URL {url:?}"))?; + let scheme = parsed_url.scheme_str().context("URL has no scheme")?; + if scheme != "https" { + bail!("POST requests to non-HTTPS URLs are not allowed"); + } + + let mut sender = get_http_sender(context, parsed_url.clone()).await?; + let authority = parsed_url + .authority() + .context("URL has no authority")? + .clone(); + let req = hyper::Request::post(parsed_url.path()) + .header(hyper::header::HOST, authority.as_str()) + .body(http_body_util::Empty::::new())?; + + let response = sender.send_request(req).await?; + if response.status().is_redirection() { + let header = response + .headers() + .get_all("location") + .iter() + .last() + .ok_or_else(|| anyhow!("Redirection doesn't have a target location"))? + .to_str()?; + info!(context, "Following redirect to {}", header); + url = header.to_string(); + continue; + } + + let response_status = response.status(); + let body = response.collect().await?.to_bytes(); + let text = String::from_utf8_lossy(&body); + let response_text = text.to_string(); + + return Ok((response_text, response_status.is_success())); } - // As only HTTPS is used, it is safe to load DNS cache. - let load_cache = true; - - let response = crate::net::http::get_client(context, load_cache) - .await? - .post(url) - .send() - .await?; - let response_status = response.status(); - let response_text = response - .text() - .await - .context("Request failed: empty response")?; - - Ok((response_text, response_status.is_success())) + Err(anyhow!("Followed 10 redirections")) }