diff --git a/Cargo.lock b/Cargo.lock index 7fe648c..e544532 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,19 @@ version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" +[[package]] +name = "async-compression" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a" +dependencies = [ + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -31,9 +44,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" -version = "0.13.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" [[package]] name = "beef" @@ -151,6 +164,15 @@ dependencies = [ "syn", ] +[[package]] +name = "encoding_rs" +version = "0.8.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +dependencies = [ + "cfg-if", +] + [[package]] name = "erased-serde" version = "0.3.24" @@ -234,6 +256,15 @@ dependencies = [ "syn", ] +[[package]] +name = "futures-channel" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +dependencies = [ + "futures-core", +] + [[package]] name = "futures-core" version = "0.3.25" @@ -251,6 +282,12 @@ dependencies = [ "syn", ] +[[package]] +name = "futures-sink" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" + [[package]] name = "futures-task" version = "0.3.25" @@ -271,6 +308,25 @@ dependencies = [ "slab", ] +[[package]] +name = "h2" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -292,6 +348,77 @@ dependencies = [ "libc", ] +[[package]] +name = "http" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" +dependencies = [ + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + [[package]] name = "idna" version = "0.3.0" @@ -322,6 +449,12 @@ dependencies = [ "windows-sys 0.42.0", ] +[[package]] +name = "ipnet" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" + [[package]] name = "is-terminal" version = "0.4.2" @@ -422,10 +555,10 @@ dependencies = [ "mlua", "os_str_bytes", "regex", + "reqwest", "serde", "serde_json", "tokio", - "ureq", ] [[package]] @@ -434,6 +567,12 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + [[package]] name = "miniz_oxide" version = "0.6.2" @@ -649,6 +788,47 @@ version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +[[package]] +name = "reqwest" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" +dependencies = [ + "async-compression", + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-rustls", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "winreg", +] + [[package]] name = "ring" version = "0.16.20" @@ -705,6 +885,15 @@ dependencies = [ "webpki", ] +[[package]] +name = "rustls-pemfile" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +dependencies = [ + "base64", +] + [[package]] name = "ryu" version = "1.0.12" @@ -764,6 +953,18 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "signal-hook-registry" version = "1.4.0" @@ -885,6 +1086,63 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls", + "tokio", + "webpki", +] + +[[package]] +name = "tokio-util" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + [[package]] name = "unicode-bidi" version = "0.3.10" @@ -912,22 +1170,6 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" -[[package]] -name = "ureq" -version = "2.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "338b31dd1314f68f3aabf3ed57ab922df95ffcd902476ca7ba3c4ce7b908c46d" -dependencies = [ - "base64", - "flate2", - "log", - "once_cell", - "rustls", - "url", - "webpki", - "webpki-roots", -] - [[package]] name = "url" version = "2.3.1" @@ -945,6 +1187,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -976,6 +1228,18 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.83" @@ -1145,3 +1409,12 @@ name = "windows_x86_64_msvc" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] diff --git a/Cargo.toml b/Cargo.toml index 57b4f68..daf40a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,10 +28,14 @@ anyhow = "1.0.68" os_str_bytes = "6.4.1" regex = "1.7.1" serde_json = "1.0.91" -ureq = "2.6.2" clap = { version = "4.1.1", features = ["derive"] } full_moon = { version = "0.17.0", features = ["roblox"] } mlua = { version = "0.8.7", features = ["luau", "async", "serialize"] } serde = { version = "1.0.152", features = ["derive"] } tokio = { version = "1.24.2", features = ["full"] } + +reqwest = { version = "0.11.14", default-features = false, features = [ + "rustls-tls", + "gzip", +] } diff --git a/src/cli/utils/github.rs b/src/cli/utils/github.rs index ccbec9b..55872ea 100644 --- a/src/cli/utils/github.rs +++ b/src/cli/utils/github.rs @@ -1,6 +1,7 @@ -use std::env::current_dir; +use std::{env::current_dir, str::FromStr}; use anyhow::{bail, Context, Result}; +use reqwest::header::{HeaderName, HeaderValue}; use serde::{Deserialize, Serialize}; use lune::utils::net::{get_github_owner_and_repo, get_request_user_agent_header}; @@ -41,15 +42,17 @@ impl Client { } } - async fn get(&self, url: &str, headers: &[(&str, &str)]) -> Result { - let mut request = ureq::get(url) - .set("User-Agent", &get_request_user_agent_header()) - .set("Accept", "application/vnd.github+json") - .set("X-GitHub-Api-Version", "2022-11-28"); + async fn get(&self, url: &str, headers: &[(&str, &str)]) -> Result> { + let mut request = reqwest::ClientBuilder::new() + .build()? + .request(reqwest::Method::GET, url) + .header("User-Agent", &get_request_user_agent_header()) + .header("Accept", "application/vnd.github+json") + .header("X-GitHub-Api-Version", "2022-11-28"); for (header, value) in headers { - request = request.set(header, value); + request = request.header(HeaderName::from_str(header)?, HeaderValue::from_str(value)?); } - tokio::task::spawn_blocking(|| Ok(request.send_string("")?.into_string()?)).await? + Ok(request.send().await?.bytes().await?.to_vec()) } pub async fn fetch_releases(&self) -> Result> { @@ -57,8 +60,8 @@ impl Client { "https://api.github.com/repos/{}/{}/releases", &self.github_owner, &self.github_repo ); - let response_string = self.get(&release_api_url, &[]).await?; - Ok(serde_json::from_str(&response_string)?) + let response_bytes = self.get(&release_api_url, &[]).await?; + Ok(serde_json::from_slice(&response_bytes)?) } pub async fn fetch_release_for_this_version(&self) -> Result { @@ -78,10 +81,10 @@ impl Client { .find(|asset| matches!(&asset.name, Some(name) if name == asset_name)) { let file_path = current_dir()?.join(asset_name); - let file_string = self + let file_bytes = self .get(&asset.url, &[("Accept", "application/octet-stream")]) .await?; - tokio::fs::write(&file_path, &file_string) + tokio::fs::write(&file_path, &file_bytes) .await .with_context(|| { format!("Failed to write file at path '{}'", &file_path.display()) diff --git a/src/lib/globals/net.rs b/src/lib/globals/net.rs index 825dbd4..a81b0bf 100644 --- a/src/lib/globals/net.rs +++ b/src/lib/globals/net.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use mlua::prelude::*; +use reqwest::Method; use crate::utils::{net::get_request_user_agent_header, table::TableBuilder}; @@ -76,42 +77,49 @@ async fn net_request<'lua>(lua: &'lua Lua, config: LuaValue<'lua>) -> LuaResult< // Convert method string into proper enum let method = method.trim().to_ascii_uppercase(); let method = match method.as_ref() { - "GET" | "POST" | "PUT" | "DELETE" | "HEAD" | "OPTIONS" | "PATCH" => Ok(&method), + "GET" => Ok(Method::GET), + "POST" => Ok(Method::POST), + "PUT" => Ok(Method::PUT), + "DELETE" => Ok(Method::DELETE), + "HEAD" => Ok(Method::HEAD), + "OPTIONS" => Ok(Method::OPTIONS), + "PATCH" => Ok(Method::PATCH), _ => Err(LuaError::RuntimeError(format!( "Invalid request config method '{}'", &method ))), }?; + // TODO: Figure out how to reuse this client + let client = reqwest::ClientBuilder::new() + .build() + .map_err(LuaError::external)?; // Create and send the request - let mut request = ureq::request(method, &url); + let mut request = client.request(method, &url); for (header, value) in headers { - request = request.set(header.to_str()?, value.to_str()?); - } - let response = request - .set("User-Agent", &get_request_user_agent_header()) // Always force user agent - .send_bytes(&body.unwrap_or_default()); - match response { - Ok(res) | Err(ureq::Error::Status(_, res)) => { - // Extract status, headers - let res_status = res.status(); - let res_status_text = res.status_text().to_owned(); - let res_header_names = &res.headers_names(); - let res_headers = res_header_names - .iter() - .map(|name| (name.to_owned(), res.header(name).unwrap().to_owned())) - .collect::>(); - // Read response bytes - let mut res_bytes = Vec::new(); - res.into_reader().read_to_end(&mut res_bytes)?; - // Construct and return a readonly lua table with results - TableBuilder::new(lua)? - .with_value("ok", (200..300).contains(&res_status))? - .with_value("statusCode", res_status)? - .with_value("statusMessage", res_status_text)? - .with_value("headers", res_headers)? - .with_value("body", lua.create_string(&res_bytes)?)? - .build_readonly() - } - Err(e) => Err(LuaError::external(e)), + request = request.header(header.to_str()?, value.to_str()?); } + let res = request + .header("User-Agent", &get_request_user_agent_header()) // Always force user agent + .body(body.unwrap_or_default()) + .send() + .await + .map_err(LuaError::external)?; + // Extract status, headers + let res_status = res.status().as_u16(); + let res_status_text = res.status().canonical_reason(); + let res_headers = res + .headers() + .iter() + .map(|(name, value)| (name.to_string(), value.to_str().unwrap().to_owned())) + .collect::>(); + // Read response bytes + let res_bytes = res.bytes().await.map_err(LuaError::external)?; + // Construct and return a readonly lua table with results + TableBuilder::new(lua)? + .with_value("ok", (200..300).contains(&res_status))? + .with_value("statusCode", res_status)? + .with_value("statusMessage", res_status_text)? + .with_value("headers", res_headers)? + .with_value("body", lua.create_string(&res_bytes)?)? + .build_readonly() }