mirror of
https://github.com/typst/typst
synced 2025-07-27 22:37:54 +08:00
Fix breaking changes caused by move to ureq 3
None of the changes cause any logic changes (I think). They just deal with stuff changed/deprecated in ureq 3.
This commit is contained in:
parent
1197092a03
commit
97430912ce
@ -145,10 +145,10 @@ impl Release {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match downloader.download(&url) {
|
match downloader.download(&url) {
|
||||||
Ok(response) => response.into_json().map_err(|err| {
|
Ok(mut response) => response.body_mut().read_json().map_err(|err| {
|
||||||
eco_format!("failed to parse release information ({err})")
|
eco_format!("failed to parse release information ({err})")
|
||||||
}),
|
}),
|
||||||
Err(ureq::Error::Status(404, _)) => {
|
Err(ureq::Error::StatusCode(404)) => {
|
||||||
bail!("release not found (searched at {url})")
|
bail!("release not found (searched at {url})")
|
||||||
}
|
}
|
||||||
Err(err) => bail!("failed to download release ({err})"),
|
Err(err) => bail!("failed to download release ({err})"),
|
||||||
@ -175,7 +175,7 @@ impl Release {
|
|||||||
&mut PrintDownload("release"),
|
&mut PrintDownload("release"),
|
||||||
) {
|
) {
|
||||||
Ok(data) => data,
|
Ok(data) => data,
|
||||||
Err(ureq::Error::Status(404, _)) => {
|
Err(ureq::Error::StatusCode(404)) => {
|
||||||
bail!("asset not found (searched for {})", asset.name);
|
bail!("asset not found (searched for {})", asset.name);
|
||||||
}
|
}
|
||||||
Err(err) => bail!("failed to download asset ({err})"),
|
Err(err) => bail!("failed to download asset ({err})"),
|
||||||
|
@ -13,9 +13,8 @@ use std::sync::Arc;
|
|||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use ecow::EcoString;
|
use ecow::EcoString;
|
||||||
use native_tls::{Certificate, TlsConnector};
|
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use ureq::Response;
|
use ureq::tls::{Certificate, RootCerts, TlsProvider};
|
||||||
|
|
||||||
/// Manages progress reporting for downloads.
|
/// Manages progress reporting for downloads.
|
||||||
pub trait Progress {
|
pub trait Progress {
|
||||||
@ -57,7 +56,7 @@ pub struct DownloadState {
|
|||||||
pub struct Downloader {
|
pub struct Downloader {
|
||||||
user_agent: EcoString,
|
user_agent: EcoString,
|
||||||
cert_path: Option<PathBuf>,
|
cert_path: Option<PathBuf>,
|
||||||
cert: OnceCell<Certificate>,
|
cert: OnceCell<Certificate<'static>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Downloader {
|
impl Downloader {
|
||||||
@ -82,7 +81,10 @@ impl Downloader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Crates a new downloader with the given user agent and certificate.
|
/// Crates a new downloader with the given user agent and certificate.
|
||||||
pub fn with_cert(user_agent: impl Into<EcoString>, cert: Certificate) -> Self {
|
pub fn with_cert(
|
||||||
|
user_agent: impl Into<EcoString>,
|
||||||
|
cert: Certificate<'static>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
user_agent: user_agent.into(),
|
user_agent: user_agent.into(),
|
||||||
cert_path: None,
|
cert_path: None,
|
||||||
@ -96,7 +98,7 @@ impl Downloader {
|
|||||||
/// - Returns `None` if `--cert` and `TYPST_CERT` are not set.
|
/// - Returns `None` if `--cert` and `TYPST_CERT` are not set.
|
||||||
/// - Returns `Some(Ok(cert))` if the certificate was loaded successfully.
|
/// - Returns `Some(Ok(cert))` if the certificate was loaded successfully.
|
||||||
/// - Returns `Some(Err(err))` if an error occurred while loading the certificate.
|
/// - Returns `Some(Err(err))` if an error occurred while loading the certificate.
|
||||||
pub fn cert(&self) -> Option<io::Result<&Certificate>> {
|
pub fn cert(&self) -> Option<io::Result<&Certificate<'static>>> {
|
||||||
self.cert_path.as_ref().map(|path| {
|
self.cert_path.as_ref().map(|path| {
|
||||||
self.cert.get_or_try_init(|| {
|
self.cert.get_or_try_init(|| {
|
||||||
let pem = std::fs::read(path)?;
|
let pem = std::fs::read(path)?;
|
||||||
@ -107,31 +109,42 @@ impl Downloader {
|
|||||||
|
|
||||||
/// Download binary data from the given url.
|
/// Download binary data from the given url.
|
||||||
#[allow(clippy::result_large_err)]
|
#[allow(clippy::result_large_err)]
|
||||||
pub fn download(&self, url: &str) -> Result<ureq::Response, ureq::Error> {
|
pub fn download(
|
||||||
let mut builder = ureq::AgentBuilder::new();
|
&self,
|
||||||
let mut tls = TlsConnector::builder();
|
url: &str,
|
||||||
|
) -> Result<ureq::http::Response<ureq::Body>, ureq::Error> {
|
||||||
|
let mut builder = ureq::config::Config::builder();
|
||||||
|
|
||||||
// Set user agent.
|
// Set user agent.
|
||||||
builder = builder.user_agent(&self.user_agent);
|
builder = builder.user_agent(&self.user_agent);
|
||||||
|
|
||||||
// Get the network proxy config from the environment and apply it.
|
// Get the network proxy config from the environment and apply it.
|
||||||
if let Some(proxy) = env_proxy::for_url_str(url)
|
if let Some(proxy) = env_proxy::for_url_str(url)
|
||||||
.to_url()
|
.to_string()
|
||||||
.and_then(|url| ureq::Proxy::new(url).ok())
|
.and_then(|url| ureq::Proxy::new(&url).ok())
|
||||||
{
|
{
|
||||||
builder = builder.proxy(proxy);
|
builder = builder.proxy(Some(proxy));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply a custom CA certificate if present.
|
// Apply a custom CA certificate if present.
|
||||||
if let Some(cert) = self.cert() {
|
let maybe_cert = self.cert().transpose()?.cloned().map_or(
|
||||||
tls.add_root_certificate(cert?.clone());
|
RootCerts::PlatformVerifier,
|
||||||
}
|
|cert| {
|
||||||
|
let certs = vec![cert];
|
||||||
|
RootCerts::Specific(Arc::new(certs))
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// Configure native TLS.
|
// Configure native TLS.
|
||||||
let connector = tls.build().map_err(io::Error::other)?;
|
let tls_config = ureq::tls::TlsConfig::builder()
|
||||||
builder = builder.tls_connector(Arc::new(connector));
|
.provider(TlsProvider::NativeTls)
|
||||||
|
.root_certs(maybe_cert);
|
||||||
|
|
||||||
builder.build().get(url).call()
|
builder = builder.tls_config(tls_config.build());
|
||||||
|
|
||||||
|
let agent = ureq::Agent::new_with_config(builder.build());
|
||||||
|
|
||||||
|
agent.get(url).call()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Download binary data from the given url and report its progress.
|
/// Download binary data from the given url and report its progress.
|
||||||
@ -170,7 +183,7 @@ const SAMPLES: usize = 5;
|
|||||||
/// over a websocket and reports its progress.
|
/// over a websocket and reports its progress.
|
||||||
struct RemoteReader<'p> {
|
struct RemoteReader<'p> {
|
||||||
/// The reader returned by the ureq::Response.
|
/// The reader returned by the ureq::Response.
|
||||||
reader: Box<dyn Read + Send + Sync + 'static>,
|
reader: ureq::BodyReader<'static>,
|
||||||
/// The download state, holding download metadata for progress reporting.
|
/// The download state, holding download metadata for progress reporting.
|
||||||
state: DownloadState,
|
state: DownloadState,
|
||||||
/// The instant at which progress was last reported.
|
/// The instant at which progress was last reported.
|
||||||
@ -184,13 +197,18 @@ impl<'p> RemoteReader<'p> {
|
|||||||
///
|
///
|
||||||
/// The 'Content-Length' header is used as a size hint for read
|
/// The 'Content-Length' header is used as a size hint for read
|
||||||
/// optimization, if present.
|
/// optimization, if present.
|
||||||
fn from_response(response: Response, progress: &'p mut dyn Progress) -> Self {
|
fn from_response(
|
||||||
|
response: ureq::http::Response<ureq::Body>,
|
||||||
|
progress: &'p mut dyn Progress,
|
||||||
|
) -> Self {
|
||||||
let content_len: Option<usize> = response
|
let content_len: Option<usize> = response
|
||||||
.header("Content-Length")
|
.headers()
|
||||||
|
.get("Content-Length")
|
||||||
|
.and_then(|header| header.to_str().ok())
|
||||||
.and_then(|header| header.parse().ok());
|
.and_then(|header| header.parse().ok());
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
reader: response.into_reader(),
|
reader: response.into_body().into_reader(),
|
||||||
last_progress: None,
|
last_progress: None,
|
||||||
state: DownloadState {
|
state: DownloadState {
|
||||||
content_len,
|
content_len,
|
||||||
|
@ -150,10 +150,10 @@ impl PackageStorage {
|
|||||||
.get_or_try_init(|| {
|
.get_or_try_init(|| {
|
||||||
let url = format!("{DEFAULT_REGISTRY}/{DEFAULT_NAMESPACE}/index.json");
|
let url = format!("{DEFAULT_REGISTRY}/{DEFAULT_NAMESPACE}/index.json");
|
||||||
match self.downloader.download(&url) {
|
match self.downloader.download(&url) {
|
||||||
Ok(response) => response.into_json().map_err(|err| {
|
Ok(mut response) => response.body_mut().read_json().map_err(|err| {
|
||||||
eco_format!("failed to parse package index: {err}")
|
eco_format!("failed to parse package index: {err}")
|
||||||
}),
|
}),
|
||||||
Err(ureq::Error::Status(404, _)) => {
|
Err(ureq::Error::StatusCode(404)) => {
|
||||||
bail!("failed to fetch package index (not found)")
|
bail!("failed to fetch package index (not found)")
|
||||||
}
|
}
|
||||||
Err(err) => bail!("failed to fetch package index ({err})"),
|
Err(err) => bail!("failed to fetch package index ({err})"),
|
||||||
@ -181,7 +181,7 @@ impl PackageStorage {
|
|||||||
|
|
||||||
let data = match self.downloader.download_with_progress(&url, progress) {
|
let data = match self.downloader.download_with_progress(&url, progress) {
|
||||||
Ok(data) => data,
|
Ok(data) => data,
|
||||||
Err(ureq::Error::Status(404, _)) => {
|
Err(ureq::Error::StatusCode(404)) => {
|
||||||
if let Ok(version) = self.determine_latest_version(&spec.versionless()) {
|
if let Ok(version) = self.determine_latest_version(&spec.versionless()) {
|
||||||
return Err(PackageError::VersionNotFound(spec.clone(), version));
|
return Err(PackageError::VersionNotFound(spec.clone(), version));
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user