Skip to content

Commit db7c5fb

Browse files
refactor(core): Remove attohttpc in favor of reqwest (#7143)
Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.studio>
1 parent 52474e4 commit db7c5fb

File tree

13 files changed

+36
-273
lines changed

13 files changed

+36
-273
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'tauri-bundler': patch
3+
---
4+
5+
Remove `attohttpc` in favor of `ureq`.

.changes/remove-attohttpc-core.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'tauri': patch
3+
---
4+
5+
Remove `attohttpc` in favor of `reqwest`.

core/tauri/Cargo.toml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ targets = [
3737
]
3838

3939
[package.metadata.cargo-udeps.ignore]
40-
normal = [ "attohttpc", "reqwest" ]
40+
normal = [ "reqwest" ]
4141

4242
[dependencies]
4343
serde_json = { version = "1.0", features = [ "raw_value" ] }
@@ -69,7 +69,6 @@ base64 = { version = "0.21", optional = true }
6969
clap = { version = "3", optional = true }
7070
reqwest = { version = "0.11", features = [ "json", "stream" ], optional = true }
7171
bytes = { version = "1", features = [ "serde" ], optional = true }
72-
attohttpc = { version = "0.22", features = [ "compress", "json", "form" ], optional = true }
7372
open = { version = "3.2", optional = true }
7473
shared_child = { version = "1.0", optional = true }
7574
os_pipe = { version = "1.0", optional = true }
@@ -141,14 +140,14 @@ updater = [
141140
"dialog-ask",
142141
"fs-extract-api"
143142
]
144-
http-api = [ "attohttpc" ]
145-
http-multipart = [ "attohttpc/multipart-form", "reqwest/multipart" ]
143+
http-api = [ "reqwest", "bytes" ]
144+
http-multipart = [ "reqwest/multipart" ]
146145
os-api = [ "sys-locale" ]
147146
shell-open-api = [ "open", "regex", "tauri-macros/shell-scope" ]
148147
fs-extract-api = [ "zip" ]
149-
reqwest-client = [ "reqwest", "bytes" ]
150-
reqwest-native-tls-vendored = [ "reqwest-client", "reqwest/native-tls-vendored" ]
151-
native-tls-vendored = [ "attohttpc/tls-vendored" ]
148+
reqwest-client = [ "http-api" ]
149+
reqwest-native-tls-vendored = [ "native-tls-vendored" ]
150+
native-tls-vendored = [ "reqwest/native-tls-vendored" ]
152151
process-command-api = [ "shared_child", "os_pipe" ]
153152
global-shortcut = [
154153
"tauri-runtime/global-shortcut",

core/tauri/src/api/error.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,13 @@ pub enum Error {
2222
#[error("user cancelled the dialog")]
2323
DialogCancelled,
2424
/// The network error.
25-
#[cfg(all(feature = "http-api", not(feature = "reqwest-client")))]
26-
#[error("Network Error: {0}")]
27-
Network(#[from] attohttpc::Error),
28-
/// The network error.
29-
#[cfg(feature = "reqwest-client")]
30-
#[cfg_attr(doc_cfg, doc(cfg(feature = "reqwest-client")))]
25+
#[cfg(feature = "http-api")]
3126
#[error("Network Error: {0}")]
3227
Network(#[from] reqwest::Error),
3328
/// HTTP method error.
3429
#[error(transparent)]
3530
HttpMethod(#[from] http::method::InvalidMethod),
3631
/// Invalid HTTP header value.
37-
#[cfg(feature = "reqwest-client")]
38-
#[cfg_attr(doc_cfg, doc(cfg(feature = "reqwest-client")))]
3932
#[error(transparent)]
4033
HttpHeaderValue(#[from] http::header::InvalidHeaderValue),
4134
/// Invalid HTTP header value.

core/tauri/src/api/http.rs

Lines changed: 0 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,8 @@ use url::Url;
1313

1414
use std::{collections::HashMap, path::PathBuf, time::Duration};
1515

16-
#[cfg(feature = "reqwest-client")]
1716
pub use reqwest::header;
1817

19-
#[cfg(not(feature = "reqwest-client"))]
20-
pub use attohttpc::header;
21-
2218
use header::{HeaderName, HeaderValue};
2319

2420
#[derive(Deserialize)]
@@ -73,13 +69,6 @@ impl ClientBuilder {
7369
}
7470

7571
/// Builds the Client.
76-
#[cfg(not(feature = "reqwest-client"))]
77-
pub fn build(self) -> crate::api::Result<Client> {
78-
Ok(Client(self))
79-
}
80-
81-
/// Builds the Client.
82-
#[cfg(feature = "reqwest-client")]
8372
pub fn build(self) -> crate::api::Result<Client> {
8473
let mut client_builder = reqwest::Client::builder();
8574

@@ -101,146 +90,9 @@ impl ClientBuilder {
10190
}
10291

10392
/// The HTTP client based on [`reqwest`].
104-
#[cfg(feature = "reqwest-client")]
10593
#[derive(Debug, Clone)]
10694
pub struct Client(reqwest::Client);
10795

108-
/// The HTTP client.
109-
#[cfg(not(feature = "reqwest-client"))]
110-
#[derive(Debug, Clone)]
111-
pub struct Client(ClientBuilder);
112-
113-
#[cfg(not(feature = "reqwest-client"))]
114-
impl Client {
115-
/// Executes an HTTP request.
116-
///
117-
/// # Examples
118-
///
119-
/// ```rust,no_run
120-
/// use tauri::api::http::{ClientBuilder, HttpRequestBuilder, ResponseType};
121-
/// async fn run_request() {
122-
/// let client = ClientBuilder::new().build().unwrap();
123-
/// let response = client.send(
124-
/// HttpRequestBuilder::new("GET", "https://www.rust-lang.org")
125-
/// .unwrap()
126-
/// .response_type(ResponseType::Binary)
127-
/// ).await;
128-
/// if let Ok(response) = response {
129-
/// let bytes = response.bytes();
130-
/// }
131-
/// }
132-
/// ```
133-
pub async fn send(&self, request: HttpRequestBuilder) -> crate::api::Result<Response> {
134-
let method = Method::from_bytes(request.method.to_uppercase().as_bytes())?;
135-
136-
let mut request_builder = attohttpc::RequestBuilder::try_new(method, &request.url)?;
137-
138-
if let Some(query) = request.query {
139-
request_builder = request_builder.params(&query);
140-
}
141-
142-
if let Some(headers) = &request.headers {
143-
for (name, value) in headers.0.iter() {
144-
request_builder = request_builder.header(name, value);
145-
}
146-
}
147-
148-
if let Some(max_redirections) = self.0.max_redirections {
149-
if max_redirections == 0 {
150-
request_builder = request_builder.follow_redirects(false);
151-
} else {
152-
request_builder = request_builder.max_redirections(max_redirections as u32);
153-
}
154-
}
155-
156-
if let Some(timeout) = request.timeout {
157-
request_builder = request_builder.timeout(timeout);
158-
}
159-
160-
let response = if let Some(body) = request.body {
161-
match body {
162-
Body::Bytes(data) => request_builder.body(attohttpc::body::Bytes(data)).send()?,
163-
Body::Text(text) => request_builder.body(attohttpc::body::Bytes(text)).send()?,
164-
Body::Json(json) => request_builder.json(&json)?.send()?,
165-
Body::Form(form_body) => {
166-
#[allow(unused_variables)]
167-
fn send_form(
168-
request_builder: attohttpc::RequestBuilder,
169-
headers: &Option<HeaderMap>,
170-
form_body: FormBody,
171-
) -> crate::api::Result<attohttpc::Response> {
172-
#[cfg(feature = "http-multipart")]
173-
if matches!(
174-
headers
175-
.as_ref()
176-
.and_then(|h| h.0.get("content-type"))
177-
.map(|v| v.as_bytes()),
178-
Some(b"multipart/form-data")
179-
) {
180-
let mut multipart = attohttpc::MultipartBuilder::new();
181-
let mut byte_cache: HashMap<String, Vec<u8>> = Default::default();
182-
183-
for (name, part) in &form_body.0 {
184-
if let FormPart::File { file, .. } = part {
185-
byte_cache.insert(name.to_string(), file.clone().try_into()?);
186-
}
187-
}
188-
for (name, part) in &form_body.0 {
189-
multipart = match part {
190-
FormPart::File {
191-
file,
192-
mime,
193-
file_name,
194-
} => {
195-
// safe to unwrap: always set by previous loop
196-
let mut file =
197-
attohttpc::MultipartFile::new(name, byte_cache.get(name).unwrap());
198-
if let Some(mime) = mime {
199-
file = file.with_type(mime)?;
200-
}
201-
if let Some(file_name) = file_name {
202-
file = file.with_filename(file_name);
203-
}
204-
multipart.with_file(file)
205-
}
206-
FormPart::Text(value) => multipart.with_text(name, value),
207-
};
208-
}
209-
return request_builder
210-
.body(multipart.build()?)
211-
.send()
212-
.map_err(Into::into);
213-
}
214-
215-
let mut form = Vec::new();
216-
for (name, part) in form_body.0 {
217-
match part {
218-
FormPart::File { file, .. } => {
219-
let bytes: Vec<u8> = file.try_into()?;
220-
form.push((name, serde_json::to_string(&bytes)?))
221-
}
222-
FormPart::Text(value) => form.push((name, value)),
223-
}
224-
}
225-
request_builder.form(&form)?.send().map_err(Into::into)
226-
}
227-
228-
send_form(request_builder, &request.headers, form_body)?
229-
}
230-
}
231-
} else {
232-
request_builder.send()?
233-
};
234-
235-
Ok(Response(
236-
request.response_type.unwrap_or(ResponseType::Json),
237-
response,
238-
request.url,
239-
))
240-
}
241-
}
242-
243-
#[cfg(feature = "reqwest-client")]
24496
impl Client {
24597
/// Executes an HTTP request
24698
///
@@ -557,13 +409,8 @@ impl HttpRequestBuilder {
557409
}
558410

559411
/// The HTTP response.
560-
#[cfg(feature = "reqwest-client")]
561412
#[derive(Debug)]
562413
pub struct Response(ResponseType, reqwest::Response);
563-
/// The HTTP response.
564-
#[cfg(not(feature = "reqwest-client"))]
565-
#[derive(Debug)]
566-
pub struct Response(ResponseType, attohttpc::Response, Url);
567414

568415
impl Response {
569416
/// Get the [`StatusCode`] of this Response.
@@ -579,20 +426,10 @@ impl Response {
579426
/// Reads the response as raw bytes.
580427
pub async fn bytes(self) -> crate::api::Result<RawResponse> {
581428
let status = self.status().as_u16();
582-
#[cfg(feature = "reqwest-client")]
583429
let data = self.1.bytes().await?.to_vec();
584-
#[cfg(not(feature = "reqwest-client"))]
585-
let data = self.1.bytes()?;
586430
Ok(RawResponse { status, data })
587431
}
588432

589-
#[cfg(not(feature = "reqwest-client"))]
590-
#[allow(dead_code)]
591-
pub(crate) fn reader(self) -> attohttpc::ResponseReader {
592-
let (_, _, reader) = self.1.split();
593-
reader
594-
}
595-
596433
// Convert the response into a Stream of [`bytes::Bytes`] from the body.
597434
//
598435
// # Examples
@@ -612,7 +449,6 @@ impl Response {
612449
// # Ok(())
613450
// # }
614451
// ```
615-
#[cfg(feature = "reqwest-client")]
616452
#[allow(dead_code)]
617453
pub(crate) fn bytes_stream(
618454
self,
@@ -625,10 +461,7 @@ impl Response {
625461
///
626462
/// Note that the body is serialized to a [`Value`].
627463
pub async fn read(self) -> crate::api::Result<ResponseData> {
628-
#[cfg(feature = "reqwest-client")]
629464
let url = self.1.url().clone();
630-
#[cfg(not(feature = "reqwest-client"))]
631-
let url = self.2;
632465

633466
let mut headers = HashMap::new();
634467
let mut raw_headers = HashMap::new();
@@ -650,20 +483,12 @@ impl Response {
650483
}
651484
let status = self.1.status().as_u16();
652485

653-
#[cfg(feature = "reqwest-client")]
654486
let data = match self.0 {
655487
ResponseType::Json => self.1.json().await?,
656488
ResponseType::Text => Value::String(self.1.text().await?),
657489
ResponseType::Binary => serde_json::to_value(&self.1.bytes().await?)?,
658490
};
659491

660-
#[cfg(not(feature = "reqwest-client"))]
661-
let data = match self.0 {
662-
ResponseType::Json => self.1.json()?,
663-
ResponseType::Text => Value::String(self.1.text()?),
664-
ResponseType::Binary => serde_json::to_value(self.1.bytes()?)?,
665-
};
666-
667492
Ok(ResponseData {
668493
url,
669494
status,

core/tauri/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
//! - **shell-open-api**: Enables the [`api::shell`] module.
2323
//! - **http-api**: Enables the [`api::http`] module.
2424
//! - **http-multipart**: Adds support to `multipart/form-data` requests.
25-
//! - **reqwest-client**: Uses `reqwest` as HTTP client on the `http` APIs. Improves performance, but increases the bundle size.
26-
//! - **native-tls-vendored**: Compile and statically link to a vendored copy of OpenSSL (applies to the default HTTP client).
27-
//! - **reqwest-native-tls-vendored**: Compile and statically link to a vendored copy of OpenSSL (applies to the `reqwest` HTTP client).
25+
//! - **reqwest-client**: Alias for the `http-api` feature flag.
26+
//! - **native-tls-vendored**: Compile and statically link to a vendored copy of OpenSSL.
27+
//! - **reqwest-native-tls-vendored**: Alias for the `native-tls-vendored` feature flag.
2828
//! - **os-api**: Enables the [`api::os`] module.
2929
//! - **process-command-api**: Enables the [`api::process::Command`] APIs.
3030
//! - **global-shortcut**: Enables the global shortcut APIs.

core/tauri/src/updater/core.rs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,6 @@ impl<R: Runtime> Update<R> {
559559
.and_then(|value| value.parse().ok());
560560

561561
let mut buffer = Vec::new();
562-
#[cfg(feature = "reqwest-client")]
563562
{
564563
use futures_util::StreamExt;
565564
let mut stream = response.bytes_stream();
@@ -570,25 +569,6 @@ impl<R: Runtime> Update<R> {
570569
buffer.extend(bytes);
571570
}
572571
}
573-
#[cfg(not(feature = "reqwest-client"))]
574-
{
575-
let mut reader = response.reader();
576-
let mut buf = [0; 16384];
577-
loop {
578-
match reader.read(&mut buf) {
579-
Ok(b) => {
580-
if b == 0 {
581-
break;
582-
} else {
583-
let bytes = buf[0..b].to_vec();
584-
on_chunk(bytes.len(), content_length);
585-
buffer.extend(bytes);
586-
}
587-
}
588-
Err(e) => return Err(e.into()),
589-
}
590-
}
591-
}
592572

593573
on_download_finish();
594574

examples/api/src-tauri/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ features = [
2929
"isolation",
3030
"macos-private-api",
3131
"windows7-compat",
32-
"reqwest-client",
3332
"system-tray",
3433
"updater"
3534
]

tooling/bundler/Cargo.toml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ tempfile = "3.5.0"
3232
log = { version = "0.4.18", features = [ "kv_unstable" ] }
3333
dirs-next = "2.0"
3434
os_pipe = "1"
35-
attohttpc = { version = "0.25", default-features = false }
35+
ureq = { version = "2.5", default-features = false }
36+
native-tls = { version = "0.2", optional = true }
3637
hex = "0.4"
3738
semver = "1"
3839
sha1 = "0.10"
@@ -64,7 +65,7 @@ name = "tauri_bundler"
6465
path = "src/lib.rs"
6566

6667
[features]
67-
default = [ "native-tls" ]
68-
native-tls = [ "attohttpc/tls-native" ]
69-
native-tls-vendored = [ "attohttpc/tls-native-vendored" ]
70-
rustls = [ "attohttpc/rustls" ]
68+
default = ["rustls"]
69+
native-tls = [ "ureq/native-tls" ]
70+
native-tls-vendored = [ "native-tls", "native-tls/vendored" ]
71+
rustls = [ "ureq/tls" ]

0 commit comments

Comments
 (0)