From 291015cb3b5095b0bbaffb4240f97beaf5d299ad Mon Sep 17 00:00:00 2001 From: Sleeyax Date: Fri, 17 Nov 2023 23:36:46 +0100 Subject: [PATCH 01/14] refactor: return string slices --- src/engine.rs | 8 ++++---- src/engine_params.rs | 16 ++++++++-------- src/error.rs | 4 ++-- src/http_header.rs | 10 ++++------ src/public_key_pins.rs | 8 ++++---- src/quic_hint.rs | 4 ++-- src/url_request_params.rs | 4 ++-- src/url_response_info.rs | 25 ++++++++++++++----------- 8 files changed, 40 insertions(+), 39 deletions(-) diff --git a/src/engine.rs b/src/engine.rs index c598370..68b3a98 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -75,21 +75,21 @@ impl Engine { } /// A human-readable version string of the engine. - pub fn version(&self) -> String { + pub fn version(&self) -> &str { unsafe { let version = Cronet_Engine_GetVersionString(self.ptr); let version = CStr::from_ptr(version); - version.to_string_lossy().into_owned() + version.to_str().unwrap() } } /// Returns the default value of the `User-Agent` header. /// Can be accessed before `StartWithParams()` is called. - pub fn default_user_agent(&self) -> String { + pub fn default_user_agent(&self) -> &str { unsafe { let version = Cronet_Engine_GetDefaultUserAgent(self.ptr); let version = CStr::from_ptr(version); - version.to_string_lossy().into_owned() + version.to_str().unwrap() } } diff --git a/src/engine_params.rs b/src/engine_params.rs index 857e387..b45c889 100644 --- a/src/engine_params.rs +++ b/src/engine_params.rs @@ -57,12 +57,12 @@ impl EngineParams { } /// Returns the `User-Agent` header value. - pub fn user_agent(&self) -> String { + pub fn user_agent(&self) -> &str { unsafe { let c_str = Cronet_EngineParams_user_agent_get(self.ptr); let c_str = CStr::from_ptr(c_str); let str_slice = c_str.to_str().unwrap(); - str_slice.to_owned() + str_slice } } @@ -75,12 +75,12 @@ impl EngineParams { } /// Returns the `Accept-Language` header value. - pub fn accept_language(&self) -> String { + pub fn accept_language(&self) -> &str { unsafe { let c_str = Cronet_EngineParams_accept_language_get(self.ptr); let c_str = CStr::from_ptr(c_str); let str_slice = c_str.to_str().unwrap(); - str_slice.to_owned() + str_slice } } @@ -94,12 +94,12 @@ impl EngineParams { } /// Returns the directory for HTTP Cache and Prefs Storage. - pub fn storage_path(&self) -> String { + pub fn storage_path(&self) -> &str { unsafe { let c_str = Cronet_EngineParams_storage_path_get(self.ptr); let c_str = CStr::from_ptr(c_str); let str_slice = c_str.to_str().unwrap(); - str_slice.to_owned() + str_slice } } @@ -257,12 +257,12 @@ impl EngineParams { } } - pub fn experimental_options(&self) -> String { + pub fn experimental_options(&self) -> &str { unsafe { let c_str = Cronet_EngineParams_experimental_options_get(self.ptr); let c_str = CStr::from_ptr(c_str); let str_slice = c_str.to_str().unwrap(); - str_slice.to_owned() + str_slice } } } diff --git a/src/error.rs b/src/error.rs index b50a132..ef544a4 100644 --- a/src/error.rs +++ b/src/error.rs @@ -49,10 +49,10 @@ impl CronetError { } /// Get the error message. - pub fn message(&self) -> String { + pub fn message(&self) -> &str { unsafe { let c_message = Cronet_Error_message_get(self.ptr); - let message = CStr::from_ptr(c_message).to_string_lossy().into_owned(); + let message = CStr::from_ptr(c_message).to_str().unwrap(); message } } diff --git a/src/http_header.rs b/src/http_header.rs index 01d94de..0f3dd8c 100644 --- a/src/http_header.rs +++ b/src/http_header.rs @@ -20,12 +20,10 @@ impl HttpHeader { } /// Get the name of this header. - pub fn name(&self) -> String { + pub fn name(&self) -> &'static str { unsafe { let c_name = Cronet_HttpHeader_name_get(self.ptr); - let name = std::ffi::CStr::from_ptr(c_name) - .to_string_lossy() - .into_owned(); + let name = std::ffi::CStr::from_ptr(c_name).to_str().unwrap(); name } } @@ -38,10 +36,10 @@ impl HttpHeader { } } - pub fn value(&self) -> String { + pub fn value(&self) -> &'static str { unsafe { let c_value = Cronet_HttpHeader_value_get(self.ptr); - let value = CStr::from_ptr(c_value).to_string_lossy().into_owned(); + let value = CStr::from_ptr(c_value).to_str().unwrap(); value } } diff --git a/src/public_key_pins.rs b/src/public_key_pins.rs index 2a2f537..07d450a 100644 --- a/src/public_key_pins.rs +++ b/src/public_key_pins.rs @@ -33,10 +33,10 @@ impl PublicKeyPins { } } - pub fn host(&self) -> String { + pub fn host(&self) -> &str { unsafe { let c_str = Cronet_PublicKeyPins_host_get(self.ptr); - let host = CStr::from_ptr(c_str).to_string_lossy().into_owned(); + let host = CStr::from_ptr(c_str).to_str().unwrap(); host } } @@ -58,10 +58,10 @@ impl PublicKeyPins { unsafe { Cronet_PublicKeyPins_pins_sha256_size(self.ptr) } } - pub fn at(&self, index: u32) -> String { + pub fn at(&self, index: u32) -> &str { unsafe { let c_str = Cronet_PublicKeyPins_pins_sha256_at(self.ptr, index); - CStr::from_ptr(c_str).to_string_lossy().into_owned() + CStr::from_ptr(c_str).to_str().unwrap() } } diff --git a/src/quic_hint.rs b/src/quic_hint.rs index 53c52ad..eb2ac6b 100644 --- a/src/quic_hint.rs +++ b/src/quic_hint.rs @@ -28,10 +28,10 @@ impl QuicHint { } } - pub fn host(&self) -> String { + pub fn host(&self) -> &str { unsafe { let c_str = Cronet_QuicHint_host_get(self.ptr); - let host = CStr::from_ptr(c_str).to_string_lossy().into_owned(); + let host = CStr::from_ptr(c_str).to_str().unwrap(); host } } diff --git a/src/url_request_params.rs b/src/url_request_params.rs index f972b24..a2eb81d 100644 --- a/src/url_request_params.rs +++ b/src/url_request_params.rs @@ -53,12 +53,12 @@ impl UrlRequestParams { } } - pub fn method(&self) -> String { + pub fn method(&self) -> &str { unsafe { let c_str = Cronet_UrlRequestParams_http_method_get(self.ptr); let c_str = CStr::from_ptr(c_str); let str_slice = c_str.to_str().unwrap(); - str_slice.to_owned() + str_slice } } diff --git a/src/url_response_info.rs b/src/url_response_info.rs index 4037722..dfc6818 100644 --- a/src/url_response_info.rs +++ b/src/url_response_info.rs @@ -1,5 +1,7 @@ use std::ffi::{CStr, CString}; +use http::{HeaderValue, Response, StatusCode, Version}; + use crate::{ Cronet_UrlResponseInfoPtr, Cronet_UrlResponseInfo_Create, Cronet_UrlResponseInfo_Destroy, Cronet_UrlResponseInfo_all_headers_list_add, Cronet_UrlResponseInfo_all_headers_list_at, @@ -31,11 +33,11 @@ impl UrlResponseInfo { /// The URL the response is for. /// This is the URL after following redirects, so it may not be the originally requested URL - pub fn url(&self) -> String { + pub fn url(&self) -> &str { unsafe { let url = Cronet_UrlResponseInfo_url_get(self.ptr); let url = CStr::from_ptr(url); - url.to_string_lossy().into_owned() + url.to_str().unwrap() } } @@ -54,11 +56,11 @@ impl UrlResponseInfo { /// The URL at the given index in the chain. /// The first entry is the originally requested URL; the following entries are redirects followed. - pub fn url_chain_at(&self, index: u32) -> String { + pub fn url_chain_at(&self, index: u32) -> &str { unsafe { let url = Cronet_UrlResponseInfo_url_chain_at(self.ptr, index); let url = CStr::from_ptr(url); - url.to_string_lossy().into_owned() + url.to_str().unwrap() } } @@ -91,11 +93,11 @@ impl UrlResponseInfo { /// The HTTP status text of the status line. /// For example, if the request received a "HTTP/1.1 200 OK" response, this method returns "OK". - pub fn status_text(&self) -> String { + pub fn status_text(&self) -> &str { unsafe { let text = Cronet_UrlResponseInfo_http_status_text_get(self.ptr); let text = CStr::from_ptr(text); - text.to_string_lossy().into_owned() + text.to_str().unwrap() } } @@ -146,11 +148,12 @@ impl UrlResponseInfo { /// The protocol (for example 'quic/1+spdy/3') negotiated with the server. /// An empty string if no protocol was negotiated, the protocol is /// not known, or when using plain HTTP or HTTPS. - pub fn negotiated_protocol(&self) -> String { + pub fn negotiated_protocol(&self) -> &'static str { unsafe { let protocol = Cronet_UrlResponseInfo_negotiated_protocol_get(self.ptr); let protocol = CStr::from_ptr(protocol); - protocol.to_string_lossy().into_owned() + let protocol = protocol.to_str().unwrap(); + protocol } } @@ -162,11 +165,11 @@ impl UrlResponseInfo { } /// The proxy server that was used for the request. - pub fn proxy_server(&self) -> String { + pub fn proxy_server(&self) -> &'static str { unsafe { let server = Cronet_UrlResponseInfo_proxy_server_get(self.ptr); - let server = CStr::from_ptr(server); - server.to_string_lossy().into_owned() + let server = CStr::from_ptr(server).to_str().unwrap(); + server } } From b652c8e05c5a14bfa8b86a826a503640cc8965a3 Mon Sep 17 00:00:00 2001 From: Sleeyax Date: Fri, 17 Nov 2023 23:37:33 +0100 Subject: [PATCH 02/14] fix: make client module public --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 6417583..2e51046 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,7 @@ mod annotation; mod buffer; mod buffer_callback; #[cfg(feature = "client")] -mod client; +pub mod client; mod date_time; mod destroy; mod engine; From e9e10d2b57dc42a7c837e59c9aa02f7a8e06c0f1 Mon Sep 17 00:00:00 2001 From: Sleeyax Date: Fri, 17 Nov 2023 23:38:19 +0100 Subject: [PATCH 03/14] feat: add mutable bytes for response body --- src/client/body.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/client/body.rs b/src/client/body.rs index 31f0121..0c3de43 100644 --- a/src/client/body.rs +++ b/src/client/body.rs @@ -1,7 +1,7 @@ // This implementation is inspired by: https://github.com/seanmonstar/reqwest/blob/6792f697fcdb27c47dcbf7bd05f23368d1d4ac80/src/blocking/body.rs // License: https://github.com/seanmonstar/reqwest/blob/master/LICENSE-MIT -use bytes::Bytes; +use bytes::{Bytes, BytesMut}; use std::fmt; use std::fs::File; use std::io::Read; @@ -30,6 +30,18 @@ impl Body { match self.kind { Kind::Reader(_, _) => None, Kind::Bytes(ref bytes) => Some(bytes.as_ref()), + Kind::BytesMut(ref bytes) => Some(bytes.as_ref()), + } + } + + /// Returns the body as a mutable byte slice. + /// Useful to build the body of a HTTP response. + /// For HTTP requests this method returns `None`. + pub fn as_bytes_mut(&mut self) -> Option<&mut BytesMut> { + match self.kind { + Kind::Reader(_, _) => None, + Kind::Bytes(_) => None, + Kind::BytesMut(ref mut bytes) => Some(bytes), } } @@ -37,6 +49,7 @@ impl Body { match self.kind { Kind::Reader(_, len) => len, Kind::Bytes(ref bytes) => Some(bytes.len() as u64), + Kind::BytesMut(ref bytes) => Some(bytes.len() as u64), } } @@ -49,6 +62,7 @@ impl Body { enum Kind { Reader(Box, Option), Bytes(Bytes), + BytesMut(BytesMut), } impl Kind { @@ -56,6 +70,15 @@ impl Kind { match self { Kind::Reader(..) => None, Kind::Bytes(v) => Some(Kind::Bytes(v.clone())), + Kind::BytesMut(v) => Some(Kind::BytesMut(v.clone())), + } + } +} + +impl Default for Body { + fn default() -> Body { + Body { + kind: Kind::BytesMut(BytesMut::new()), } } } @@ -118,6 +141,7 @@ impl fmt::Debug for Kind { .field("length", &DebugLength(v)) .finish(), Kind::Bytes(ref v) => fmt::Debug::fmt(v, f), + Kind::BytesMut(ref v) => fmt::Debug::fmt(v, f), } } } From ada24a90c83c5e88d08b3295ea0bc68f97bfbf4e Mon Sep 17 00:00:00 2001 From: Sleeyax Date: Fri, 17 Nov 2023 23:44:29 +0100 Subject: [PATCH 04/14] refactor: mutable self on url request callback --- src/url_request_callback.rs | 57 +++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/src/url_request_callback.rs b/src/url_request_callback.rs index 846220f..eb9af0b 100644 --- a/src/url_request_callback.rs +++ b/src/url_request_callback.rs @@ -20,8 +20,8 @@ unsafe extern "C" fn cronetUrlRequestCallbackOnRedirectReceived( info_ptr: Cronet_UrlResponseInfoPtr, new_location_url: Cronet_String, ) { - let lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap(); - let callback = lockedMap.get(&self_ptr).unwrap(); + let mut lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap(); + let callback = lockedMap.get_mut(&self_ptr).unwrap(); let c_str = CStr::from_ptr(new_location_url); let new_location_url = c_str.to_str().unwrap(); callback.on_redirect_received( @@ -38,8 +38,8 @@ unsafe extern "C" fn cronetUrlRequestCallbackOnResponseStarted( request_ptr: Cronet_UrlRequestPtr, info_ptr: Cronet_UrlResponseInfoPtr, ) { - let lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap(); - let callback = lockedMap.get(&self_ptr).unwrap(); + let mut lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap(); + let callback = lockedMap.get_mut(&self_ptr).unwrap(); callback.on_response_started( UrlRequestCallback { ptr: self_ptr }, UrlRequest { ptr: request_ptr }, @@ -55,8 +55,8 @@ unsafe extern "C" fn cronetUrlRequestCallbackOnReadCompleted( buffer_ptr: Cronet_BufferPtr, bytes_read: u64, ) { - let lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap(); - let callback = lockedMap.get(&self_ptr).unwrap(); + let mut lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap(); + let callback = lockedMap.get_mut(&self_ptr).unwrap(); callback.on_read_completed( UrlRequestCallback { ptr: self_ptr }, UrlRequest { ptr: request_ptr }, @@ -72,8 +72,8 @@ unsafe extern "C" fn cronetUrlRequestCallbackOnSucceeded( request_ptr: Cronet_UrlRequestPtr, info_ptr: Cronet_UrlResponseInfoPtr, ) { - let lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap(); - let callback = lockedMap.get(&self_ptr).unwrap(); + let mut lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap(); + let callback = lockedMap.get_mut(&self_ptr).unwrap(); callback.on_succeeded( UrlRequestCallback { ptr: self_ptr }, UrlRequest { ptr: request_ptr }, @@ -88,8 +88,8 @@ unsafe extern "C" fn cronetUrlRequestCallbackOnFailed( info_ptr: Cronet_UrlResponseInfoPtr, error_ptr: Cronet_ErrorPtr, ) { - let lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap(); - let callback = lockedMap.get(&self_ptr).unwrap(); + let mut lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap(); + let callback = lockedMap.get_mut(&self_ptr).unwrap(); callback.on_failed( UrlRequestCallback { ptr: self_ptr }, UrlRequest { ptr: request_ptr }, @@ -104,8 +104,8 @@ unsafe extern "C" fn cronetUrlRequestCallbackOnCanceled( request_ptr: Cronet_UrlRequestPtr, info_ptr: Cronet_UrlResponseInfoPtr, ) { - let lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap(); - let callback = lockedMap.get(&self_ptr).unwrap(); + let mut lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap(); + let callback = lockedMap.get_mut(&self_ptr).unwrap(); callback.on_canceled( UrlRequestCallback { ptr: self_ptr }, UrlRequest { ptr: request_ptr }, @@ -168,7 +168,7 @@ pub trait UrlRequestCallbackHandler { /// * `info`: Response information. /// * `newLocationUrl`: Location where the request is redirected. fn on_redirect_received( - &self, + &mut self, url_request_callback: UrlRequestCallback, request: UrlRequest, info: UrlResponseInfo, @@ -189,7 +189,7 @@ pub trait UrlRequestCallbackHandler { /// * `request`: Request that started to get the response. /// * `info`: Response information. fn on_response_started( - &self, + &mut self, url_request_callback: UrlRequestCallback, request: UrlRequest, info: UrlResponseInfo, @@ -214,7 +214,7 @@ pub trait UrlRequestCallbackHandler { /// containing the received data. /// * `bytesRead`: The number of bytes read into the `buffer`. fn on_read_completed( - &self, + &mut self, url_request_callback: UrlRequestCallback, request: UrlRequest, info: UrlResponseInfo, @@ -233,7 +233,7 @@ pub trait UrlRequestCallbackHandler { /// * `request`: Request that succeeded. /// * `info`: Response information. NOTE: this is owned by the request. fn on_succeeded( - &self, + &mut self, url_request_callback: UrlRequestCallback, request: UrlRequest, info: UrlResponseInfo, @@ -252,7 +252,7 @@ pub trait UrlRequestCallbackHandler { /// * `info`: Response information. May be `None` if no response was received. NOTE: this is owned by the request. /// * `error`: Information about the error. NOTE: this is owned by the request. fn on_failed( - &self, + &mut self, url_request_callback: UrlRequestCallback, request: UrlRequest, info: UrlResponseInfo, @@ -270,7 +270,7 @@ pub trait UrlRequestCallbackHandler { /// * `request`: Request that was canceled. /// * `info`: Response information. May be `None` if no response was received. NOTE: this is owned by the request. fn on_canceled( - &self, + &mut self, url_request_callback: UrlRequestCallback, request: UrlRequest, info: UrlResponseInfo, @@ -287,7 +287,7 @@ mod tests { impl UrlRequestCallbackHandler for TestUrlRequestCallbackHandler { fn on_redirect_received( - &self, + &mut self, _: UrlRequestCallback, _: UrlRequest, _: UrlResponseInfo, @@ -296,10 +296,17 @@ mod tests { println!("on_redirect_received"); } - fn on_response_started(&self, _: UrlRequestCallback, _: UrlRequest, _: UrlResponseInfo) {} + fn on_response_started( + &mut self, + _: UrlRequestCallback, + _: UrlRequest, + _: UrlResponseInfo, + ) { + println!("on_response_started") + } fn on_read_completed( - &self, + &mut self, _: UrlRequestCallback, _: UrlRequest, _: UrlResponseInfo, @@ -309,10 +316,12 @@ mod tests { println!("on_read_completed"); } - fn on_succeeded(&self, _: UrlRequestCallback, _: UrlRequest, _: UrlResponseInfo) {} + fn on_succeeded(&mut self, _: UrlRequestCallback, _: UrlRequest, _: UrlResponseInfo) { + println!("on_succeeded"); + } fn on_failed( - &self, + &mut self, _: UrlRequestCallback, _: UrlRequest, _: UrlResponseInfo, @@ -321,7 +330,7 @@ mod tests { println!("on_failed"); } - fn on_canceled(&self, _: UrlRequestCallback, _: UrlRequest, _: UrlResponseInfo) { + fn on_canceled(&mut self, _: UrlRequestCallback, _: UrlRequest, _: UrlResponseInfo) { println!("on_canceled"); } } From 9ffecb343021255ef94c089f7d1eac00c84ad3ca Mon Sep 17 00:00:00 2001 From: Sleeyax Date: Fri, 17 Nov 2023 23:45:22 +0100 Subject: [PATCH 05/14] feat: add blocking client example (WIP) --- .vscode/launch.json | 6 +- examples/blocking.rs | 12 ++++ src/client/client.rs | 35 +++++++++--- src/client/mod.rs | 2 + src/client/response_handler.rs | 101 +++++++++++++++++++++++++++++++++ src/url_request.rs | 8 +-- src/url_response_info.rs | 39 +++++++++++++ 7 files changed, 188 insertions(+), 15 deletions(-) create mode 100644 examples/blocking.rs create mode 100644 src/client/response_handler.rs diff --git a/.vscode/launch.json b/.vscode/launch.json index f42a57f..a28e4ef 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -29,15 +29,15 @@ { "type": "lldb", "request": "launch", - "name": "Debug example 'buffer'", + "name": "Debug example 'blocking'", "cargo": { "args": [ "build", - "--example=buffer", + "--example=blocking", "--package=cronet-rs" ], "filter": { - "name": "buffer", + "name": "blocking", "kind": "example" } }, diff --git a/examples/blocking.rs b/examples/blocking.rs new file mode 100644 index 0000000..7929f78 --- /dev/null +++ b/examples/blocking.rs @@ -0,0 +1,12 @@ +use cronet_rs::client::{Body, Client}; + +fn main() { + let client = Client::new(); + let request = http::Request::builder() + .method("GET") + .uri("https://httpbin.org/anything") + .body(Body::default()) + .unwrap(); + let result = client.send(request); + println!("{:?}", result); +} diff --git a/src/client/client.rs b/src/client/client.rs index fa0c22d..7df607a 100644 --- a/src/client/client.rs +++ b/src/client/client.rs @@ -1,10 +1,10 @@ -use std::thread; +use std::{sync::mpsc, thread}; -use crate::{Destroy, Engine, EngineParams, Executor, UrlRequestParams}; +use crate::{ + Destroy, Engine, EngineParams, Executor, UrlRequest, UrlRequestCallback, UrlRequestParams, +}; -use super::Body; - -type ShouldRedirectFn = fn(new_location_url: &str) -> bool; +use super::{Body, ResponseHandler, ShouldRedirectFn, Status}; pub struct Client { pub should_redirect: ShouldRedirectFn, @@ -51,12 +51,31 @@ impl Client { self.should_redirect = should_redirect; } - pub fn send(&self, request: http::Request) -> http::Result> { + pub fn send(&self, request: http::Request) -> http::Result> { + let uri = request.uri().to_string(); + let request_parameters = UrlRequestParams::from(request); request_parameters.set_upload_data_executor(&self.executor); - // TODO: implement response handler + // TODO: fix and complete example; it's currently stuck somewhere during the request + let (tx, rx) = mpsc::channel::<(http::Response, Status)>(); + let response_handler = ResponseHandler::new(self.should_redirect, tx); + let callback = UrlRequestCallback::new(response_handler); + let url_request = UrlRequest::new(); + url_request.init_with_params( + &self.engine, + uri.as_str(), + &request_parameters, + &callback, + &self.executor, + ); + // request_parameters.destroy(); + let result = url_request.start(); + println!("result: {:?}", result); + + let (response, status) = rx.recv().unwrap(); + println!("status: {:?}", status); - http::Result::Ok(http::Response::new(Body::from(""))) + http::Result::Ok(response) } } diff --git a/src/client/mod.rs b/src/client/mod.rs index f7a4312..0c44f01 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -1,7 +1,9 @@ mod body; mod body_upload_provider; mod client; +mod response_handler; pub use body::*; pub use body_upload_provider::*; pub use client::*; +pub use response_handler::*; diff --git a/src/client/response_handler.rs b/src/client/response_handler.rs new file mode 100644 index 0000000..e0ff2b2 --- /dev/null +++ b/src/client/response_handler.rs @@ -0,0 +1,101 @@ +use std::sync::mpsc::Sender; + +use bytes::BufMut; +use http::Response; + +use crate::{ + Buffer, CronetError, UrlRequest, UrlRequestCallback, UrlRequestCallbackHandler, UrlResponseInfo, +}; + +use super::Body; + +pub type ShouldRedirectFn = fn(new_location_url: &str) -> bool; + +#[derive(Debug)] +pub enum Status { + Success, + Canceled, + Error(CronetError), +} + +pub struct ResponseHandler { + pub should_redirect: ShouldRedirectFn, + response: Response, + tx: Sender<(Response, Status)>, +} + +impl ResponseHandler { + pub fn new(should_redirect: ShouldRedirectFn, tx: Sender<(Response, Status)>) -> Self { + Self { + should_redirect, + response: Response::default(), + tx, + } + } +} + +impl UrlRequestCallbackHandler for ResponseHandler { + fn on_redirect_received( + &mut self, + _: UrlRequestCallback, + request: UrlRequest, + info: UrlResponseInfo, + new_location_url: &str, + ) { + let redirect = (self.should_redirect)(new_location_url); + + if !redirect { + self.response = info.into(); + return; + } + + request.follow_redirect(); + } + + fn on_response_started(&mut self, _: UrlRequestCallback, _: UrlRequest, info: UrlResponseInfo) { + self.response = info.into(); + } + + fn on_read_completed( + &mut self, + _: UrlRequestCallback, + _: UrlRequest, + _: UrlResponseInfo, + buffer: Buffer, + bytes_read: u64, + ) { + if bytes_read == 0 { + return; + } + + let data = buffer.data::<&[u8]>(); + self.response.body_mut().as_bytes_mut().unwrap().put(data); + } + + fn on_succeeded(&mut self, _: UrlRequestCallback, _: UrlRequest, _: UrlResponseInfo) { + // TODO: fix lifetime of response to sender + self.tx + .send((Response::default(), Status::Success)) + .unwrap(); + } + + fn on_failed( + &mut self, + _: UrlRequestCallback, + _: UrlRequest, + _: UrlResponseInfo, + error: CronetError, + ) { + // TODO: fix lifetime of response to sender + self.tx + .send((Response::default(), Status::Error(error))) + .unwrap(); + } + + fn on_canceled(&mut self, _: UrlRequestCallback, _: UrlRequest, _: UrlResponseInfo) { + // TODO: fix lifetime of response to sender + self.tx + .send((Response::default(), Status::Canceled)) + .unwrap(); + } +} diff --git a/src/url_request.rs b/src/url_request.rs index 5544c6c..e377572 100644 --- a/src/url_request.rs +++ b/src/url_request.rs @@ -36,11 +36,11 @@ impl UrlRequest { /// * `executor` - Executor on which all callbacks will be invoked. pub fn init_with_params( &self, - engine: Engine, + engine: &Engine, url: &str, - params: UrlRequestParams, - callback: UrlRequestCallback, - executor: Executor, + params: &UrlRequestParams, + callback: &UrlRequestCallback, + executor: &Executor, ) -> EngineResult { unsafe { let c_str = CString::new(url).unwrap(); diff --git a/src/url_response_info.rs b/src/url_response_info.rs index dfc6818..b69ea18 100644 --- a/src/url_response_info.rs +++ b/src/url_response_info.rs @@ -200,6 +200,45 @@ impl Destroy for UrlResponseInfo { } } +#[cfg(feature = "client")] +impl Into> for UrlResponseInfo +where + T: Default, +{ + fn into(self) -> Response { + let mut response = Response::default(); + + // Set HTTP version + let version = match self.negotiated_protocol() { + "http/0.9" => Version::HTTP_09, + "http/1.0" => Version::HTTP_10, + "http/1.1" => Version::HTTP_11, + "h2" => Version::HTTP_2, + "h3" => Version::HTTP_3, + "" => Version::HTTP_11, + version => panic!("Server responded with unknown HTTP version '{}'", version), + }; + *response.version_mut() = version; + + // Set status code + let status_code = self.status_code(); + *response.status_mut() = StatusCode::from_u16(status_code as u16).unwrap(); + + // Set headers + let header_size = self.header_size(); + for i in 0..header_size { + let header = self.header_at(i); + let name = header.name(); + let value = header.value(); + response + .headers_mut() + .insert(name, HeaderValue::from_static(value)); + } + + response + } +} + #[cfg(test)] mod tests { use crate::Destroy; From 7d7d24d35dc894456303f1b63f91467bf187b6af Mon Sep 17 00:00:00 2001 From: Sleeyax Date: Thu, 28 Dec 2023 17:24:42 +0100 Subject: [PATCH 06/14] docs: update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index fb96c9f..e19f4a6 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ $ cd cronet-rs Then, follow the steps to build the project: -1. Get the latest cronet binaries: [build from source](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/components/cronet/build_instructions.md) or get prebuilt binaries from somewhere (if you know a reputable source, [let me know](https://github.com/sleeyax/cronet-rs/issues/new)!). +1. Get the latest cronet binaries: [build from source](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/components/cronet/build_instructions.md) or download prebuilt binaries from [here](https://github.com/sleeyax/cronet-binaries/releases). 2. Place all `.h` header files in `src` and all binaries (`.so`, `.dll`, `.dylib`) in `bin`. 3. Run `cargo build`. This should trigger `bindgen` to (re)generate the bindings. @@ -24,12 +24,12 @@ Then, follow the steps to build the project: Maintenance of this project is made possible by all the contributors and sponsors. If you'd like to sponsor this project and have your avatar or company logo appear below click [here](https://github.com/sponsors/sleeyax). 💖 -SecretKeys +SecretKeys ## Related projects Other projects that are related to this project and might interest you: -- [Cronet in C#](https://github.com/sleeyax/CronetSharp) -- [Cronet in go](https://github.com/SagerNet/cronet-go) +- [Cronet bindings for C#](https://github.com/sleeyax/CronetSharp) +- [Cronet bindings for go](https://github.com/sleeyax/cronet-go) - [NaïveProxy](https://github.com/klzgrad/naiveproxy) From 5aaefea54213d72be1daa89018220dae0e26ecaf Mon Sep 17 00:00:00 2001 From: Sleeyax Date: Thu, 28 Dec 2023 21:21:25 +0100 Subject: [PATCH 07/14] feat: finish blocking client example --- examples/blocking.rs | 14 +++++- src/buffer.rs | 13 +++++- src/client/client.rs | 18 ++++---- src/client/error.rs | 34 ++++++++++++++ src/client/mod.rs | 2 + src/client/response_handler.rs | 83 ++++++++++++++++++++++------------ 6 files changed, 123 insertions(+), 41 deletions(-) create mode 100644 src/client/error.rs diff --git a/examples/blocking.rs b/examples/blocking.rs index 7929f78..ad2708d 100644 --- a/examples/blocking.rs +++ b/examples/blocking.rs @@ -8,5 +8,17 @@ fn main() { .body(Body::default()) .unwrap(); let result = client.send(request); - println!("{:?}", result); + print_result(result); +} + +fn print_result(result: Result, cronet_rs::client::ClientError>) { + match result { + Ok(response) => { + println!("Status: {}", response.status()); + println!("Headers: {:#?}", response.headers()); + let body = response.body().as_bytes().unwrap(); + println!("Body: {}", String::from_utf8_lossy(body)); + } + Err(error) => println!("Error: {:?}", error), + } } diff --git a/src/buffer.rs b/src/buffer.rs index 24373ef..640a63a 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -1,3 +1,5 @@ +use std::slice; + use crate::{ BufferCallback, Cronet_BufferPtr, Cronet_Buffer_Create, Cronet_Buffer_Destroy, Cronet_Buffer_GetData, Cronet_Buffer_GetSize, Cronet_Buffer_InitWithAlloc, @@ -55,6 +57,10 @@ impl Buffer { unsafe { Cronet_Buffer_GetSize(self.ptr) } } + pub(crate) fn data_ptr(&self) -> Cronet_RawDataPtr { + unsafe { Cronet_Buffer_GetData(self.ptr) } + } + pub fn data(&self) -> Box { unsafe { let dataPtr: Cronet_RawDataPtr = self.data_ptr(); @@ -62,8 +68,11 @@ impl Buffer { } } - pub(crate) fn data_ptr(&self) -> Cronet_RawDataPtr { - unsafe { Cronet_Buffer_GetData(self.ptr) } + pub fn data_slice(&self, size: usize) -> &[T] { + unsafe { + let slice = slice::from_raw_parts(self.data_ptr() as *mut T, size); + slice + } } /// Write arbitrary data to the buffer. diff --git a/src/client/client.rs b/src/client/client.rs index 7df607a..f02e986 100644 --- a/src/client/client.rs +++ b/src/client/client.rs @@ -1,7 +1,8 @@ use std::{sync::mpsc, thread}; use crate::{ - Destroy, Engine, EngineParams, Executor, UrlRequest, UrlRequestCallback, UrlRequestParams, + client::ClientError, Destroy, Engine, EngineParams, Executor, UrlRequest, UrlRequestCallback, + UrlRequestParams, }; use super::{Body, ResponseHandler, ShouldRedirectFn, Status}; @@ -51,14 +52,13 @@ impl Client { self.should_redirect = should_redirect; } - pub fn send(&self, request: http::Request) -> http::Result> { + pub fn send(&self, request: http::Request) -> Result, ClientError> { let uri = request.uri().to_string(); let request_parameters = UrlRequestParams::from(request); request_parameters.set_upload_data_executor(&self.executor); - // TODO: fix and complete example; it's currently stuck somewhere during the request - let (tx, rx) = mpsc::channel::<(http::Response, Status)>(); + let (tx, rx) = mpsc::channel::(); let response_handler = ResponseHandler::new(self.should_redirect, tx); let callback = UrlRequestCallback::new(response_handler); let url_request = UrlRequest::new(); @@ -71,11 +71,13 @@ impl Client { ); // request_parameters.destroy(); let result = url_request.start(); - println!("result: {:?}", result); - let (response, status) = rx.recv().unwrap(); - println!("status: {:?}", status); + let status = rx.recv().unwrap(); - http::Result::Ok(response) + match status { + Status::Success(res) => Result::Ok(res), + Status::Canceled => Result::Err(ClientError::CancellationError), + Status::Error(e) => Result::Err(ClientError::CronetError(e)), + } } } diff --git a/src/client/error.rs b/src/client/error.rs new file mode 100644 index 0000000..53d9918 --- /dev/null +++ b/src/client/error.rs @@ -0,0 +1,34 @@ +use core::fmt; + +use crate::CronetError; + +pub enum ClientError { + /// Internal cronet error. + CronetError(CronetError), + /// The request was cancelled. + CancellationError, +} + +impl From for ClientError { + fn from(error: CronetError) -> Self { + Self::CronetError(error) + } +} + +impl fmt::Display for ClientError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::CronetError(error) => write!(f, "{}", error), + Self::CancellationError => write!(f, "Request was cancelled"), + } + } +} + +impl fmt::Debug for ClientError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::CronetError(error) => write!(f, "{:?}", error), + Self::CancellationError => write!(f, "Request was cancelled"), + } + } +} diff --git a/src/client/mod.rs b/src/client/mod.rs index 0c44f01..e3d8660 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -1,9 +1,11 @@ mod body; mod body_upload_provider; mod client; +mod error; mod response_handler; pub use body::*; pub use body_upload_provider::*; pub use client::*; +pub use error::*; pub use response_handler::*; diff --git a/src/client/response_handler.rs b/src/client/response_handler.rs index e0ff2b2..dc54726 100644 --- a/src/client/response_handler.rs +++ b/src/client/response_handler.rs @@ -1,10 +1,11 @@ -use std::sync::mpsc::Sender; +use std::{mem, sync::mpsc::Sender}; use bytes::BufMut; use http::Response; use crate::{ - Buffer, CronetError, UrlRequest, UrlRequestCallback, UrlRequestCallbackHandler, UrlResponseInfo, + Buffer, CronetError, Destroy, UrlRequest, UrlRequestCallback, UrlRequestCallbackHandler, + UrlResponseInfo, }; use super::Body; @@ -13,25 +14,47 @@ pub type ShouldRedirectFn = fn(new_location_url: &str) -> bool; #[derive(Debug)] pub enum Status { - Success, + Success(Response), Canceled, Error(CronetError), } pub struct ResponseHandler { - pub should_redirect: ShouldRedirectFn, + should_redirect: ShouldRedirectFn, response: Response, - tx: Sender<(Response, Status)>, + tx: Sender, + buffer: Option, + buffer_size: u64, } impl ResponseHandler { - pub fn new(should_redirect: ShouldRedirectFn, tx: Sender<(Response, Status)>) -> Self { + pub fn new(should_redirect: ShouldRedirectFn, tx: Sender) -> Self { Self { should_redirect, response: Response::default(), tx, + buffer: None, + buffer_size: 512, } } + + /// Sets the buffer size for reading the response body. + /// The default is `512` bytes. + pub fn set_buffer_size(&mut self, buffer_size: u64) { + self.buffer_size = buffer_size; + } + + /// Continues reading the response body. + fn read(&mut self, req: UrlRequest) { + if let Some(old_buffer) = &self.buffer { + old_buffer.destroy(); + } + + let buffer = Buffer::new_with_size(self.buffer_size); + self.buffer = Some(Buffer { ptr: buffer.ptr }); + + req.read(buffer); + } } impl UrlRequestCallbackHandler for ResponseHandler { @@ -42,24 +65,27 @@ impl UrlRequestCallbackHandler for ResponseHandler { info: UrlResponseInfo, new_location_url: &str, ) { - let redirect = (self.should_redirect)(new_location_url); - - if !redirect { + if (self.should_redirect)(new_location_url) { + request.follow_redirect(); + } else { self.response = info.into(); - return; } - - request.follow_redirect(); } - fn on_response_started(&mut self, _: UrlRequestCallback, _: UrlRequest, info: UrlResponseInfo) { + fn on_response_started( + &mut self, + _: UrlRequestCallback, + req: UrlRequest, + info: UrlResponseInfo, + ) { self.response = info.into(); + self.read(req); } fn on_read_completed( &mut self, _: UrlRequestCallback, - _: UrlRequest, + req: UrlRequest, _: UrlResponseInfo, buffer: Buffer, bytes_read: u64, @@ -68,34 +94,31 @@ impl UrlRequestCallbackHandler for ResponseHandler { return; } - let data = buffer.data::<&[u8]>(); + let data = buffer.data_slice::(bytes_read as usize); self.response.body_mut().as_bytes_mut().unwrap().put(data); + + self.read(req); } - fn on_succeeded(&mut self, _: UrlRequestCallback, _: UrlRequest, _: UrlResponseInfo) { - // TODO: fix lifetime of response to sender - self.tx - .send((Response::default(), Status::Success)) - .unwrap(); + fn on_succeeded(&mut self, _: UrlRequestCallback, req: UrlRequest, _: UrlResponseInfo) { + req.destroy(); + let response = mem::replace(&mut self.response, Response::default()); + self.tx.send(Status::Success(response)).unwrap(); } fn on_failed( &mut self, _: UrlRequestCallback, - _: UrlRequest, + req: UrlRequest, _: UrlResponseInfo, error: CronetError, ) { - // TODO: fix lifetime of response to sender - self.tx - .send((Response::default(), Status::Error(error))) - .unwrap(); + req.destroy(); + self.tx.send(Status::Error(error)).unwrap(); } - fn on_canceled(&mut self, _: UrlRequestCallback, _: UrlRequest, _: UrlResponseInfo) { - // TODO: fix lifetime of response to sender - self.tx - .send((Response::default(), Status::Canceled)) - .unwrap(); + fn on_canceled(&mut self, _: UrlRequestCallback, req: UrlRequest, _: UrlResponseInfo) { + req.destroy(); + self.tx.send(Status::Canceled).unwrap(); } } From 77e225ff42cb7034b8c8cddbda5f79599165c5f7 Mon Sep 17 00:00:00 2001 From: Sleeyax Date: Thu, 28 Dec 2023 22:09:44 +0100 Subject: [PATCH 08/14] fix: disable chunked uploads by specifying `false` --- src/upload_data_provider.rs | 2 +- src/upload_data_sink.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/upload_data_provider.rs b/src/upload_data_provider.rs index e632305..d2e76f5 100644 --- a/src/upload_data_provider.rs +++ b/src/upload_data_provider.rs @@ -177,7 +177,7 @@ mod tests { fn read(&self, _: UploadDataProvider, sink: UploadDataSink, buffer: Buffer) { let size = buffer.size(); - sink.on_read_succeeded(size, true); + sink.on_read_succeeded(size, false); } fn rewind(&mut self, _: UploadDataProvider, sink: UploadDataSink) { diff --git a/src/upload_data_sink.rs b/src/upload_data_sink.rs index da90899..ba0fe13 100644 --- a/src/upload_data_sink.rs +++ b/src/upload_data_sink.rs @@ -163,7 +163,7 @@ mod tests { on_rewind_succeeded: |_| println!("on_rewind_succeeded"), on_rewind_error: |_, _| println!("on_rewind_error"), }); - upload_data_sink.on_read_succeeded(10, true); + upload_data_sink.on_read_succeeded(10, false); upload_data_sink.on_rewind_succeeded(); upload_data_sink.on_read_error("error"); upload_data_sink.on_rewind_error("error"); From 0c3e6df70a0d933854d446e7a15fe6bfef5fd507 Mon Sep 17 00:00:00 2001 From: Sleeyax Date: Thu, 28 Dec 2023 22:10:22 +0100 Subject: [PATCH 09/14] feat: add method to write slice of arbitrary data to buffer --- src/buffer.rs | 20 +++++++++++++++++++- src/client/body_upload_provider.rs | 4 ++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/buffer.rs b/src/buffer.rs index 640a63a..b37c3a5 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -83,7 +83,8 @@ impl Buffer { /// /// * `data` - The data to write to the buffer. /// * `data_size` - The size of the data to write to the buffer. Must be less than or equal to the buffer's size. - pub fn write(&self, data: Box, data_size: u64) -> Result<(), &'static str> { + #[allow(dead_code)] + pub(crate) fn write(&self, data: Box, data_size: u64) -> Result<(), &'static str> { let src = Box::into_raw(data); let src_size = data_size; let dst = self.data_ptr() as *mut T; @@ -99,6 +100,23 @@ impl Buffer { Ok(()) } + + pub(crate) fn write_slice(&self, data: &[T], data_size: u64) -> Result<(), &'static str> { + let src = data.as_ptr(); + let src_size = data_size; + let dst = self.data_ptr() as *mut T; + let dst_size = self.size(); + + if dst_size < src_size { + return Err("Buffer is too small to hold the specified data"); + } + + unsafe { + std::ptr::copy_nonoverlapping(src, dst, src_size as usize); + } + + Ok(()) + } } impl Destroy for Buffer { diff --git a/src/client/body_upload_provider.rs b/src/client/body_upload_provider.rs index c7de2de..9071fb7 100644 --- a/src/client/body_upload_provider.rs +++ b/src/client/body_upload_provider.rs @@ -29,9 +29,9 @@ impl<'a> UploadDataProviderHandler for BodyUploadDataProvider<'a> { return; } - match buffer.write(Box::new(bytes), len) { + match buffer.write_slice(bytes, len) { Ok(_) => { - sink.on_read_succeeded(len, true); // TODO: implement chunked reads + sink.on_read_succeeded(len, false); // TODO: implement chunked reads } Err(err) => { sink.on_read_error(err); From c48468cb12d7b401ed64b61fea1b19bfb32c02c8 Mon Sep 17 00:00:00 2001 From: Sleeyax Date: Thu, 28 Dec 2023 22:17:13 +0100 Subject: [PATCH 10/14] feat: update blocking example --- examples/blocking.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/examples/blocking.rs b/examples/blocking.rs index ad2708d..b8ad8da 100644 --- a/examples/blocking.rs +++ b/examples/blocking.rs @@ -2,6 +2,8 @@ use cronet_rs::client::{Body, Client}; fn main() { let client = Client::new(); + + println!("sending GET request..."); let request = http::Request::builder() .method("GET") .uri("https://httpbin.org/anything") @@ -9,6 +11,16 @@ fn main() { .unwrap(); let result = client.send(request); print_result(result); + + println!("sending POST request..."); + let request = http::Request::builder() + .method("POST") + .uri("https://httpbin.org/anything") + .header("content-type", "application/x-www-form-urlencoded") + .body(Body::from("Hello, world")) + .unwrap(); + let result = client.send(request); + print_result(result); } fn print_result(result: Result, cronet_rs::client::ClientError>) { From a6536740782603401dc1f2c96c96ff2eb9f06710 Mon Sep 17 00:00:00 2001 From: Sleeyax Date: Thu, 28 Dec 2023 22:19:57 +0100 Subject: [PATCH 11/14] feat: handle engine errors --- src/client/client.rs | 7 +++++-- src/client/error.rs | 6 +++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/client/client.rs b/src/client/client.rs index f02e986..33f2aee 100644 --- a/src/client/client.rs +++ b/src/client/client.rs @@ -1,8 +1,8 @@ use std::{sync::mpsc, thread}; use crate::{ - client::ClientError, Destroy, Engine, EngineParams, Executor, UrlRequest, UrlRequestCallback, - UrlRequestParams, + client::ClientError, Destroy, Engine, EngineParams, EngineResult, Executor, UrlRequest, + UrlRequestCallback, UrlRequestParams, }; use super::{Body, ResponseHandler, ShouldRedirectFn, Status}; @@ -71,6 +71,9 @@ impl Client { ); // request_parameters.destroy(); let result = url_request.start(); + if result != EngineResult::Success { + return Result::Err(ClientError::EngineError(result)); + } let status = rx.recv().unwrap(); diff --git a/src/client/error.rs b/src/client/error.rs index 53d9918..42b6b2d 100644 --- a/src/client/error.rs +++ b/src/client/error.rs @@ -1,12 +1,14 @@ use core::fmt; -use crate::CronetError; +use crate::{CronetError, EngineResult}; pub enum ClientError { /// Internal cronet error. CronetError(CronetError), /// The request was cancelled. CancellationError, + /// Unexpected cronet engine result. + EngineError(EngineResult), } impl From for ClientError { @@ -20,6 +22,7 @@ impl fmt::Display for ClientError { match self { Self::CronetError(error) => write!(f, "{}", error), Self::CancellationError => write!(f, "Request was cancelled"), + Self::EngineError(error) => write!(f, "Unexpected engine result: {:?}", error), } } } @@ -29,6 +32,7 @@ impl fmt::Debug for ClientError { match self { Self::CronetError(error) => write!(f, "{:?}", error), Self::CancellationError => write!(f, "Request was cancelled"), + Self::EngineError(error) => write!(f, "Unexpected engine result: {:?}", error), } } } From fe647ab3a134a53e049faa0a805e27373023805d Mon Sep 17 00:00:00 2001 From: Sleeyax Date: Thu, 28 Dec 2023 22:41:41 +0100 Subject: [PATCH 12/14] refactor: improve error logging --- examples/blocking.rs | 2 +- src/client/error.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/blocking.rs b/examples/blocking.rs index b8ad8da..7df6a02 100644 --- a/examples/blocking.rs +++ b/examples/blocking.rs @@ -31,6 +31,6 @@ fn print_result(result: Result, cronet_rs::client::ClientEr let body = response.body().as_bytes().unwrap(); println!("Body: {}", String::from_utf8_lossy(body)); } - Err(error) => println!("Error: {:?}", error), + Err(error) => println!("Error: {}", error), } } diff --git a/src/client/error.rs b/src/client/error.rs index 42b6b2d..cdbf132 100644 --- a/src/client/error.rs +++ b/src/client/error.rs @@ -30,7 +30,7 @@ impl fmt::Display for ClientError { impl fmt::Debug for ClientError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self::CronetError(error) => write!(f, "{:?}", error), + Self::CronetError(error) => write!(f, "{}", error), Self::CancellationError => write!(f, "Request was cancelled"), Self::EngineError(error) => write!(f, "Unexpected engine result: {:?}", error), } From 8dcbd59390ed3a792f204cffad6698f26b05ba97 Mon Sep 17 00:00:00 2001 From: Sleeyax Date: Thu, 28 Dec 2023 22:44:15 +0100 Subject: [PATCH 13/14] fix: fix tests --- src/client/body_upload_provider.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/body_upload_provider.rs b/src/client/body_upload_provider.rs index 9071fb7..b448f92 100644 --- a/src/client/body_upload_provider.rs +++ b/src/client/body_upload_provider.rs @@ -100,9 +100,9 @@ mod tests { // Read the modified buffer again by its pointer. let buffer = Buffer { ptr }; - let actual = buffer.data::<&[u8]>(); + let actual = buffer.data_slice::(4); assert_eq!(actual.len(), expected.len()); - assert_eq!(*actual, expected.as_bytes()); + assert_eq!(actual, expected.as_bytes()); buffer.destroy(); } From 9cb60c6dcf4a8842d482d11316e744187ed331b2 Mon Sep 17 00:00:00 2001 From: Sleeyax Date: Thu, 28 Dec 2023 23:10:37 +0100 Subject: [PATCH 14/14] chore: address clippy warnings --- src/buffer_callback.rs | 2 +- src/client/client.rs | 6 ++++++ src/client/mod.rs | 1 + src/client/response_handler.rs | 2 +- src/date_time.rs | 6 ++++++ src/engine.rs | 6 ++++++ src/engine_params.rs | 6 ++++++ src/error.rs | 6 ++++++ src/executor.rs | 2 +- src/http_header.rs | 6 ++++++ src/metrics.rs | 21 +++++++++------------ src/public_key_pins.rs | 6 ++++++ src/quic_hint.rs | 6 ++++++ src/request_finished_info.rs | 6 ++++++ src/request_finished_info_listener.rs | 13 +++++++------ src/runnable.rs | 2 +- src/upload_data_provider.rs | 9 +++++---- src/upload_data_sink.rs | 2 +- src/url_request.rs | 6 ++++++ src/url_request_callback.rs | 2 +- src/url_request_params.rs | 6 ++++++ src/url_request_status_listener.rs | 8 +++++++- src/url_response_info.rs | 12 ++++++++---- 23 files changed, 109 insertions(+), 33 deletions(-) diff --git a/src/buffer_callback.rs b/src/buffer_callback.rs index 13cc888..78c00ca 100644 --- a/src/buffer_callback.rs +++ b/src/buffer_callback.rs @@ -6,7 +6,7 @@ use crate::{ }; static mut BUFFER_CALLBACKS: Lazy> = - Lazy::new(|| CronetCallbacks::new()); + Lazy::new(CronetCallbacks::new); #[no_mangle] unsafe extern "C" fn cronetBufferCallbackOnDestroy( diff --git a/src/client/client.rs b/src/client/client.rs index 33f2aee..5e942cb 100644 --- a/src/client/client.rs +++ b/src/client/client.rs @@ -84,3 +84,9 @@ impl Client { } } } + +impl Default for Client { + fn default() -> Self { + Self::new() + } +} diff --git a/src/client/mod.rs b/src/client/mod.rs index e3d8660..c0d9d4a 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -1,5 +1,6 @@ mod body; mod body_upload_provider; +#[allow(clippy::module_inception)] mod client; mod error; mod response_handler; diff --git a/src/client/response_handler.rs b/src/client/response_handler.rs index dc54726..f4aa55e 100644 --- a/src/client/response_handler.rs +++ b/src/client/response_handler.rs @@ -102,7 +102,7 @@ impl UrlRequestCallbackHandler for ResponseHandler { fn on_succeeded(&mut self, _: UrlRequestCallback, req: UrlRequest, _: UrlResponseInfo) { req.destroy(); - let response = mem::replace(&mut self.response, Response::default()); + let response = mem::take(&mut self.response); self.tx.send(Status::Success(response)).unwrap(); } diff --git a/src/date_time.rs b/src/date_time.rs index f3bfc57..ada7bea 100644 --- a/src/date_time.rs +++ b/src/date_time.rs @@ -48,6 +48,12 @@ impl Destroy for DateTime { } } +impl Default for DateTime { + fn default() -> Self { + Self::new() + } +} + #[cfg(test)] mod tests { use std::time::UNIX_EPOCH; diff --git a/src/engine.rs b/src/engine.rs index 68b3a98..b10bb4c 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -110,6 +110,12 @@ impl Destroy for Engine { } } +impl Default for Engine { + fn default() -> Self { + Self::new() + } +} + #[cfg(test)] mod tests { use crate::Destroy; diff --git a/src/engine_params.rs b/src/engine_params.rs index b45c889..5863d84 100644 --- a/src/engine_params.rs +++ b/src/engine_params.rs @@ -273,6 +273,12 @@ impl Destroy for EngineParams { } } +impl Default for EngineParams { + fn default() -> Self { + Self::new() + } +} + #[derive(Debug, PartialEq)] pub enum HttpCacheMode { /// Disable HTTP cache. diff --git a/src/error.rs b/src/error.rs index ef544a4..630b4b4 100644 --- a/src/error.rs +++ b/src/error.rs @@ -116,6 +116,12 @@ impl Destroy for CronetError { } } +impl Default for CronetError { + fn default() -> Self { + Self::new() + } +} + impl fmt::Display for CronetError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( diff --git a/src/executor.rs b/src/executor.rs index 8eaf4ee..1fe9983 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -6,7 +6,7 @@ use crate::{ }; static mut EXECUTOR_CALLBACKS: Lazy> = - Lazy::new(|| CronetCallbacks::new()); + Lazy::new(CronetCallbacks::new); #[no_mangle] unsafe extern "C" fn cronetExecutorOnExecute( diff --git a/src/http_header.rs b/src/http_header.rs index 0f3dd8c..9c4b6ae 100644 --- a/src/http_header.rs +++ b/src/http_header.rs @@ -58,6 +58,12 @@ impl Destroy for HttpHeader { } } +impl Default for HttpHeader { + fn default() -> Self { + Self::new() + } +} + #[cfg(test)] mod tests { use crate::Destroy; diff --git a/src/metrics.rs b/src/metrics.rs index 155fa48..3da3ed8 100644 --- a/src/metrics.rs +++ b/src/metrics.rs @@ -161,24 +161,15 @@ impl Metrics { } pub fn socket_reused(&self) -> bool { - unsafe { - let reused = Cronet_Metrics_socket_reused_get(self.ptr); - reused - } + unsafe { Cronet_Metrics_socket_reused_get(self.ptr) } } pub fn sent_byte_count(&self) -> i64 { - unsafe { - let count = Cronet_Metrics_sent_byte_count_get(self.ptr); - count - } + unsafe { Cronet_Metrics_sent_byte_count_get(self.ptr) } } pub fn received_byte_count(&self) -> i64 { - unsafe { - let count = Cronet_Metrics_received_byte_count_get(self.ptr); - count - } + unsafe { Cronet_Metrics_received_byte_count_get(self.ptr) } } pub fn set_request_start(&self, datetime: DateTime) { @@ -284,6 +275,12 @@ impl Destroy for Metrics { } } +impl Default for Metrics { + fn default() -> Self { + Self::new() + } +} + #[cfg(test)] mod tests { use std::time::SystemTime; diff --git a/src/public_key_pins.rs b/src/public_key_pins.rs index 07d450a..6c26210 100644 --- a/src/public_key_pins.rs +++ b/src/public_key_pins.rs @@ -111,6 +111,12 @@ impl Destroy for PublicKeyPins { } } +impl Default for PublicKeyPins { + fn default() -> Self { + Self::new() + } +} + #[cfg(test)] mod tests { use std::time::UNIX_EPOCH; diff --git a/src/quic_hint.rs b/src/quic_hint.rs index eb2ac6b..a021548 100644 --- a/src/quic_hint.rs +++ b/src/quic_hint.rs @@ -65,6 +65,12 @@ impl Destroy for QuicHint { } } +impl Default for QuicHint { + fn default() -> Self { + Self::new() + } +} + #[cfg(test)] mod tests { use crate::Destroy; diff --git a/src/request_finished_info.rs b/src/request_finished_info.rs index 8d3ddcf..3cc3123 100644 --- a/src/request_finished_info.rs +++ b/src/request_finished_info.rs @@ -87,6 +87,12 @@ impl Destroy for RequestFinishedInfo { } } +impl Default for RequestFinishedInfo { + fn default() -> Self { + Self::new() + } +} + /// Enum representing the reason why the request finished. #[derive(Debug, PartialEq)] pub enum RequestFinishedInfoReason { diff --git a/src/request_finished_info_listener.rs b/src/request_finished_info_listener.rs index e036e79..1f38676 100644 --- a/src/request_finished_info_listener.rs +++ b/src/request_finished_info_listener.rs @@ -10,7 +10,7 @@ use crate::{ static mut REQUEST_FINISHED_INFO_LISTENER_CALLBACKS: Lazy< CronetCallbacks, -> = Lazy::new(|| CronetCallbacks::new()); +> = Lazy::new(CronetCallbacks::new); #[no_mangle] unsafe extern "C" fn cronetOnRequestFinished( @@ -50,10 +50,9 @@ impl RequestFinishedInfoListener { } } - pub fn set_client_context(&self, raw_data: Cronet_RawDataPtr) { - unsafe { - Cronet_RequestFinishedInfoListener_SetClientContext(self.ptr, raw_data); - } + #[allow(clippy::missing_safety_doc)] + pub unsafe fn set_client_context(&self, raw_data: Cronet_RawDataPtr) { + Cronet_RequestFinishedInfoListener_SetClientContext(self.ptr, raw_data); } } @@ -84,7 +83,9 @@ mod tests { #[test] fn it_sets_client_context() { let listener = super::RequestFinishedInfoListener::new(|_, _, _, _| {}); - listener.set_client_context(std::ptr::null_mut()); + unsafe { + listener.set_client_context(std::ptr::null_mut()); + } listener.destroy(); } } diff --git a/src/runnable.rs b/src/runnable.rs index bbe5e96..3a9e1d7 100644 --- a/src/runnable.rs +++ b/src/runnable.rs @@ -6,7 +6,7 @@ use crate::{ }; static mut RUNNABLE_CALLBACKS: Lazy> = - Lazy::new(|| CronetCallbacks::new()); + Lazy::new(CronetCallbacks::new); #[no_mangle] unsafe extern "C" fn cronetRunnableOnRun(selfPtr: Cronet_RunnablePtr) { diff --git a/src/upload_data_provider.rs b/src/upload_data_provider.rs index d2e76f5..159276e 100644 --- a/src/upload_data_provider.rs +++ b/src/upload_data_provider.rs @@ -11,7 +11,7 @@ use crate::{ static mut UPLOAD_DATA_PROVIDER_CALLBACKS: Lazy< CronetCallbacks>, -> = Lazy::new(|| CronetCallbacks::new()); +> = Lazy::new(CronetCallbacks::new); #[no_mangle] unsafe extern "C" fn cronetUploadDataProviderGetLength( @@ -19,7 +19,7 @@ unsafe extern "C" fn cronetUploadDataProviderGetLength( ) -> i64 { let lockedMap = UPLOAD_DATA_PROVIDER_CALLBACKS.map().lock().unwrap(); let callback = lockedMap.get(&selfPtr).unwrap(); - return callback.length(UploadDataProvider { ptr: selfPtr }); + callback.length(UploadDataProvider { ptr: selfPtr }) } #[no_mangle] @@ -105,8 +105,9 @@ impl UploadDataProvider { } } - pub fn set_client_context(&self, client_context: Cronet_ClientContext) { - unsafe { Cronet_UploadDataProvider_SetClientContext(self.ptr, client_context) } + #[allow(clippy::missing_safety_doc)] + pub unsafe fn set_client_context(&self, client_context: Cronet_ClientContext) { + Cronet_UploadDataProvider_SetClientContext(self.ptr, client_context) } pub fn client_context(&self) -> Cronet_ClientContext { diff --git a/src/upload_data_sink.rs b/src/upload_data_sink.rs index ba0fe13..e8194f5 100644 --- a/src/upload_data_sink.rs +++ b/src/upload_data_sink.rs @@ -11,7 +11,7 @@ use crate::{ static mut UPLOAD_DATA_SINK_CALLBACKS: Lazy< CronetCallbacks, -> = Lazy::new(|| CronetCallbacks::new()); +> = Lazy::new(CronetCallbacks::new); #[no_mangle] unsafe extern "C" fn cronetUploadDataSinkOnReadSucceeded( diff --git a/src/url_request.rs b/src/url_request.rs index e377572..fd7bdf2 100644 --- a/src/url_request.rs +++ b/src/url_request.rs @@ -134,3 +134,9 @@ impl Destroy for UrlRequest { } } } + +impl Default for UrlRequest { + fn default() -> Self { + Self::new() + } +} diff --git a/src/url_request_callback.rs b/src/url_request_callback.rs index eb9af0b..0170164 100644 --- a/src/url_request_callback.rs +++ b/src/url_request_callback.rs @@ -11,7 +11,7 @@ use crate::{ static mut URL_REQUEST_CALLBACK_CALLBACKS: Lazy< CronetCallbacks>, -> = Lazy::new(|| CronetCallbacks::new()); +> = Lazy::new(CronetCallbacks::new); #[no_mangle] unsafe extern "C" fn cronetUrlRequestCallbackOnRedirectReceived( diff --git a/src/url_request_params.rs b/src/url_request_params.rs index a2eb81d..da8304d 100644 --- a/src/url_request_params.rs +++ b/src/url_request_params.rs @@ -270,6 +270,12 @@ impl Destroy for UrlRequestParams { } } +impl Default for UrlRequestParams { + fn default() -> Self { + Self::new() + } +} + #[cfg(feature = "client")] impl From> for UrlRequestParams where diff --git a/src/url_request_status_listener.rs b/src/url_request_status_listener.rs index 3eae5d5..9dd3097 100644 --- a/src/url_request_status_listener.rs +++ b/src/url_request_status_listener.rs @@ -8,7 +8,7 @@ use crate::{ static mut URL_REQUEST_STATUS_LISTENER_CALLBACKS: Lazy< CronetCallbacks, -> = Lazy::new(|| CronetCallbacks::new()); +> = Lazy::new(CronetCallbacks::new); #[no_mangle] unsafe extern "C" fn cronetUrlRequestStatusListenerOnStatus( @@ -53,6 +53,12 @@ impl Destroy for UrlRequestStatusListener { } } +impl Default for UrlRequestStatusListener { + fn default() -> Self { + Self::new() + } +} + /// Enum representing the status of a [crate::UrlRequest]. #[derive(Debug, PartialEq)] pub enum UrlRequestStatus { diff --git a/src/url_response_info.rs b/src/url_response_info.rs index b69ea18..ccff671 100644 --- a/src/url_response_info.rs +++ b/src/url_response_info.rs @@ -109,10 +109,7 @@ impl UrlResponseInfo { } pub fn header_size(&self) -> u32 { - unsafe { - let size = Cronet_UrlResponseInfo_all_headers_list_size(self.ptr); - size - } + unsafe { Cronet_UrlResponseInfo_all_headers_list_size(self.ptr) } } pub fn header_at(&self, index: u32) -> HttpHeader { @@ -200,7 +197,14 @@ impl Destroy for UrlResponseInfo { } } +impl Default for UrlResponseInfo { + fn default() -> Self { + Self::new() + } +} + #[cfg(feature = "client")] +#[allow(clippy::from_over_into)] impl Into> for UrlResponseInfo where T: Default,