改用 rust 实现的 http client

This commit is contained in:
2024-02-07 00:20:06 +08:00
parent a3f6ecf8b6
commit 7e1352c0be
14 changed files with 589 additions and 40 deletions

View File

@ -9,7 +9,10 @@ crate-type = ["cdylib", "staticlib"]
[dependencies]
flutter_rust_bridge = "=2.0.0-dev.23"
http-downloader = { version = "0.3.2", features = ["status-tracker", "speed-tracker", "breakpoint-resume", "bson-file-archiver"] }
tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] }
tokio = { version = "1", features = ["full"] }
url = "2.5.0"
uuid = { version = "1.7.0", features = ["v4", "fast-rng", "macro-diagnostics"] }
async-std = "1.12.0"
once_cell = "1.19.0"
reqwest = { version = "0.11", features = ["rustls-tls-native-roots", "cookies", "gzip", "brotli", "deflate", "multipart", "trust-dns", "json"] }
serde_json = { version = "1.0.1", features = [] }

View File

40
rust/src/api/http_api.rs Normal file
View File

@ -0,0 +1,40 @@
use std::collections::HashMap;
use std::time::Duration;
use once_cell::sync::Lazy;
use reqwest;
use reqwest::header::{HeaderMap, HeaderValue};
use reqwest::RequestBuilder;
static HTTP_CLIENT: Lazy<reqwest::Client> = Lazy::new(|| {
let mut header_map = HeaderMap::new();
header_map.insert("User-Agent", HeaderValue::from_static("SCToolBox/2.10.x lib_rust_http"));
reqwest::Client::builder()
.use_rustls_tls()
.connect_timeout(Duration::from_secs(10))
.timeout(Duration::from_secs(10))
.default_headers(header_map).build().unwrap()
});
#[tokio::main]
pub async fn get_string(url: String, headers: Option<HashMap<String, String>>) -> String {
let mut req = _append_header(HTTP_CLIENT.get(url), headers);
req.send().await.unwrap().text().await.unwrap()
}
pub async fn post_json_string(url: String, headers: Option<HashMap<String, String>>, json_data: Option<String>) -> String {
let mut req = _append_header(HTTP_CLIENT.post(url), headers);
if json_data.is_some() {
req = req.body(json_data.unwrap()).header(reqwest::header::CONTENT_TYPE, "application/json");
}
req.send().await.unwrap().text().await.unwrap()
}
fn _append_header(mut req: RequestBuilder, headers: Option<HashMap<String, String>>) -> RequestBuilder {
if headers.is_some() {
for x in headers.unwrap() {
req = req.header(x.0, x.1);
}
}
req
}

View File

@ -3,4 +3,4 @@
//
pub mod downloader_api;
mod http;
pub mod http_api;

View File

@ -120,9 +120,96 @@ fn wire_start_download_impl(
},
)
}
fn wire_get_string_impl(
port_: flutter_rust_bridge::for_generated::MessagePort,
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
rust_vec_len_: i32,
data_len_: i32,
) {
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::SseCodec, _, _>(
flutter_rust_bridge::for_generated::TaskInfo {
debug_name: "get_string",
port: Some(port_),
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
},
move || {
let message = unsafe {
flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(
ptr_,
rust_vec_len_,
data_len_,
)
};
let mut deserializer =
flutter_rust_bridge::for_generated::SseDeserializer::new(message);
let api_url = <String>::sse_decode(&mut deserializer);
let api_headers =
<Option<std::collections::HashMap<String, String>>>::sse_decode(&mut deserializer);
deserializer.end();
move |context| {
transform_result_sse((move || {
Result::<_, ()>::Ok(crate::api::http_api::get_string(api_url, api_headers))
})())
}
},
)
}
fn wire_post_json_string_impl(
port_: flutter_rust_bridge::for_generated::MessagePort,
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
rust_vec_len_: i32,
data_len_: i32,
) {
FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec, _, _, _>(
flutter_rust_bridge::for_generated::TaskInfo {
debug_name: "post_json_string",
port: Some(port_),
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
},
move || {
let message = unsafe {
flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(
ptr_,
rust_vec_len_,
data_len_,
)
};
let mut deserializer =
flutter_rust_bridge::for_generated::SseDeserializer::new(message);
let api_url = <String>::sse_decode(&mut deserializer);
let api_headers =
<Option<std::collections::HashMap<String, String>>>::sse_decode(&mut deserializer);
let api_json_data = <Option<String>>::sse_decode(&mut deserializer);
deserializer.end();
move |context| async move {
transform_result_sse(
(move || async move {
Result::<_, ()>::Ok(
crate::api::http_api::post_json_string(
api_url,
api_headers,
api_json_data,
)
.await,
)
})()
.await,
)
}
},
)
}
// Section: dart2rust
impl SseDecode for std::collections::HashMap<String, String> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
let mut inner = <Vec<(String, String)>>::sse_decode(deserializer);
return inner.into_iter().collect();
}
}
impl SseDecode for String {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
@ -168,6 +255,18 @@ impl SseDecode for Vec<u8> {
}
}
impl SseDecode for Vec<(String, String)> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
let mut len_ = <i32>::sse_decode(deserializer);
let mut ans_ = vec![];
for idx_ in 0..len_ {
ans_.push(<(String, String)>::sse_decode(deserializer));
}
return ans_;
}
}
impl SseDecode for crate::downloader::MyDownloaderStatus {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
@ -212,6 +311,39 @@ impl SseDecode for crate::downloader::MyNetworkItemPendingType {
}
}
impl SseDecode for Option<std::collections::HashMap<String, String>> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
if (<bool>::sse_decode(deserializer)) {
return Some(<std::collections::HashMap<String, String>>::sse_decode(
deserializer,
));
} else {
return None;
}
}
}
impl SseDecode for Option<String> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
if (<bool>::sse_decode(deserializer)) {
return Some(<String>::sse_decode(deserializer));
} else {
return None;
}
}
}
impl SseDecode for (String, String) {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
let mut var_field0 = <String>::sse_decode(deserializer);
let mut var_field1 = <String>::sse_decode(deserializer);
return (var_field0, var_field1);
}
}
impl SseDecode for u64 {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
@ -249,6 +381,8 @@ fn pde_ffi_dispatcher_primary_impl(
match func_id {
2 => wire_cancel_download_impl(port, ptr, rust_vec_len, data_len),
1 => wire_start_download_impl(port, ptr, rust_vec_len, data_len),
3 => wire_get_string_impl(port, ptr, rust_vec_len, data_len),
4 => wire_post_json_string_impl(port, ptr, rust_vec_len, data_len),
_ => unreachable!(),
}
}
@ -341,6 +475,13 @@ impl flutter_rust_bridge::IntoIntoDart<crate::downloader::MyNetworkItemPendingTy
}
}
impl SseEncode for std::collections::HashMap<String, String> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
<Vec<(String, String)>>::sse_encode(self.into_iter().collect(), serializer);
}
}
impl SseEncode for String {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
@ -376,6 +517,16 @@ impl SseEncode for Vec<u8> {
}
}
impl SseEncode for Vec<(String, String)> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
<i32>::sse_encode(self.len() as _, serializer);
for item in self {
<(String, String)>::sse_encode(item, serializer);
}
}
}
impl SseEncode for crate::downloader::MyDownloaderStatus {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
@ -419,6 +570,34 @@ impl SseEncode for crate::downloader::MyNetworkItemPendingType {
}
}
impl SseEncode for Option<std::collections::HashMap<String, String>> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
<bool>::sse_encode(self.is_some(), serializer);
if let Some(value) = self {
<std::collections::HashMap<String, String>>::sse_encode(value, serializer);
}
}
}
impl SseEncode for Option<String> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
<bool>::sse_encode(self.is_some(), serializer);
if let Some(value) = self {
<String>::sse_encode(value, serializer);
}
}
}
impl SseEncode for (String, String) {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
<String>::sse_encode(self.0, serializer);
<String>::sse_encode(self.1, serializer);
}
}
impl SseEncode for u64 {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {