curl_http_client/
lib.rs

1//! curl-http-client: This is a wrapper for [Easy2](https://docs.rs/curl/latest/curl/easy/struct.Easy2.html) from [curl-rust](https://docs.rs/curl/latest/curl) crate for ergonomic use
2//! and is able to perform synchronously and asynchronously using [async-curl](https://docs.rs/async-curl/latest/async_curl) crate that uses an actor model
3//! (Message passing) to achieve a non-blocking I/O.
4//! This requires a dependency with the [curl](https://crates.io/crates/curl), [async-curl](https://crates.io/crates/async-curl)
5//! [http](https://crates.io/crates/http), [url](https://crates.io/crates/url) and [tokio](https://crates.io/crates/tokio) crates
6//!
7//! # Asynchronous Examples
8//! ## Get Request
9//! ```rust,no_run
10//! use async_curl::CurlActor;
11//! use curl_http_client::*;
12//! use http::{Method, Request};
13//! use url::Url;
14//!
15//! #[tokio::main(flavor = "current_thread")]
16//! async fn main() {
17//!     let actor = CurlActor::new();
18//!     let collector = Collector::Ram(Vec::new());
19//!
20//!     let request = Request::builder()
21//!         .uri("<SOURCE URL>")
22//!         .method(Method::GET)
23//!         .body(None)
24//!         .unwrap();
25//!
26//!     let response = HttpClient::new(collector)
27//!         .request(request).unwrap()
28//!         .nonblocking(actor)
29//!         .perform()
30//!         .await.unwrap();
31//!
32//!     println!("Response: {:?}", response);
33//! }
34//! ```
35//!
36//! ## Post Request
37//! ```rust,no_run
38//! use async_curl::CurlActor;
39//! use curl_http_client::*;
40//! use http::{Method, Request};
41//! use url::Url;
42//!
43//! #[tokio::main(flavor = "current_thread")]
44//! async fn main() {
45//!     let actor = CurlActor::new();
46//!     let collector = Collector::Ram(Vec::new());
47//!
48//!     let request = Request::builder()
49//!         .uri("<TARGET URL>")
50//!         .method(Method::POST)
51//!         .body(Some("test body".as_bytes().to_vec()))
52//!         .unwrap();
53//!
54//!     let response = HttpClient::new(collector)
55//!         .request(request).unwrap()
56//!         .nonblocking(actor)
57//!         .perform()
58//!         .await.unwrap();
59//!
60//!     println!("Response: {:?}", response);
61//! }
62//! ```
63//!
64//! ## Downloading a File
65//! ```rust,no_run
66//! use std::path::PathBuf;
67//!
68//! use async_curl::CurlActor;
69//! use curl_http_client::*;
70//! use http::{Method, Request};
71//! use url::Url;
72//!
73//! #[tokio::main(flavor = "current_thread")]
74//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
75//!     let actor = CurlActor::new();
76//!
77//!     let collector = Collector::File(FileInfo::path(PathBuf::from("<FILE PATH TO SAVE>")));
78//!
79//!     let request = Request::builder()
80//!         .uri("<SOURCE URL>")
81//!         .method(Method::GET)
82//!         .body(None)
83//!         .unwrap();
84//!
85//!     let response = HttpClient::new(collector)
86//!         .request(request)
87//!         .unwrap()
88//!         .nonblocking(actor)
89//!         .perform()
90//!         .await.unwrap();
91//!
92//!     println!("Response: {:?}", response);
93//!     Ok(())
94//! }
95//! ```
96//!
97//! ## Uploading a File
98//! ```rust,no_run
99//! use std::{fs, path::PathBuf};
100//!
101//! use async_curl::CurlActor;
102//! use curl_http_client::*;
103//! use http::{HeaderMap, Method, Request};
104//! use url::Url;
105//!
106//! #[tokio::main(flavor = "current_thread")]
107//! async fn main() {
108//!     let file_to_be_uploaded = PathBuf::from("<FILE PATH TO BE UPLOADED>");
109//!     let file_size = fs::metadata(file_to_be_uploaded.as_path()).unwrap().len() as usize;
110//!
111//!     let actor = CurlActor::new();
112//!     let collector = Collector::File(FileInfo::path(file_to_be_uploaded));
113//!
114//!     let request = Request::builder()
115//!         .uri("<TARGET URL>")
116//!         .method(Method::PUT)
117//!         .body(None)
118//!         .unwrap();
119//!
120//!     let response = HttpClient::new(collector)
121//!         .upload_file_size(FileSize::from(file_size)).unwrap()
122//!         .request(request).unwrap()
123//!         .nonblocking(actor)
124//!         .perform()
125//!         .await.unwrap();
126//!
127//!     println!("Response: {:?}", response);
128//! }
129//! ```
130//!
131//! ## Concurrency
132//! ```rust,no_run
133//! use async_curl::CurlActor;
134//! use curl_http_client::*;
135//! use futures::future;
136//! use http::{HeaderMap, Method, Request};
137//! use url::Url;
138//!
139//! #[tokio::main(flavor = "current_thread")]
140//! async fn main() {
141//!     const NUM_CONCURRENT: usize = 5;
142//!
143//!     let actor = CurlActor::new();
144//!     let mut handles = Vec::new();
145//!
146//!     for _n in 0..NUM_CONCURRENT {
147//!         let actor = actor.clone();
148//!
149//!         let handle = tokio::spawn(async move {
150//!             let collector = Collector::Ram(Vec::new());
151//!             let request = Request::builder()
152//!                 .uri("https://www.rust-lang.org/")
153//!                 .method(Method::GET)
154//!                 .body(None)
155//!                 .unwrap();
156//!
157//!             let response = HttpClient::new(collector)
158//!                 .request(request)
159//!                 .unwrap()
160//!                 .nonblocking(actor)
161//!                 .perform()
162//!                 .await
163//!                 .unwrap();
164//!             println!("Response: {:?}", response);
165//!         });
166//!         handles.push(handle);
167//!     }
168//!
169//!     let results: Vec<Result<_, _>> = future::join_all(handles).await;
170//!
171//!     for (_i, result) in results.into_iter().enumerate() {
172//!         result.unwrap();
173//!     }
174//! }
175//! ```
176//!
177//! ## Resume Downloading a File
178//! ```rust,no_run
179//! use std::fs;
180//! use std::path::PathBuf;
181//!
182//! use async_curl::CurlActor;
183//! use curl_http_client::*;
184//! use http::{HeaderMap, Method, Request};
185//! use url::Url;
186//!
187//! #[tokio::main(flavor = "current_thread")]
188//! async fn main() {
189//!     let actor = CurlActor::new();
190//!     let save_to = PathBuf::from("<FILE PATH TO SAVE>");
191//!     let collector = Collector::File(FileInfo::path(save_to.clone()));
192//!
193//!     let partial_download_file_size = fs::metadata(save_to.as_path()).unwrap().len() as usize;
194//!     let request = Request::builder()
195//!         .uri("<SOURCE URL>")
196//!         .method(Method::GET)
197//!         .body(None)
198//!         .unwrap();
199//!
200//!     let response = HttpClient::new(collector)
201//!         .resume_from(BytesOffset::from(partial_download_file_size)).unwrap()
202//!         .request(request).unwrap()
203//!         .nonblocking(actor)
204//!         .perform()
205//!         .await.unwrap();
206//!
207//!     println!("Response: {:?}", response);
208//! }
209//! ```
210//!
211//! ## Downloading a File with download speed information sent to different task
212//! ```rust,no_run
213//! use std::path::PathBuf;
214//!
215//! use async_curl::CurlActor;
216//! use curl_http_client::*;
217//! use http::{HeaderMap, Method, Request};
218//! use tokio::sync::mpsc::channel;
219//! use url::Url;
220//!
221//! #[tokio::main(flavor = "current_thread")]
222//! async fn main() {
223//!     let (tx, mut rx) = channel(1);
224//!
225//!     let actor = CurlActor::new();
226//!     let file_info = FileInfo::path(PathBuf::from("<FILE PATH TO SAVE>")).with_transfer_speed_sender(tx);
227//!     let collector = Collector::File(file_info);
228//!
229//!     let handle = tokio::spawn(async move {
230//!         while let Some(speed) = rx.recv().await {
231//!             println!("Download Speed: {} kB/s", speed.as_bytes_per_sec());
232//!         }
233//!     });
234//!
235//!     let request = Request::builder()
236//!         .uri("<SOURCE URL>")
237//!         .method(Method::GET)
238//!         .body(None)
239//!         .unwrap();
240//!
241//!     let response = HttpClient::new(collector)
242//!         .request(request).unwrap()
243//!         .nonblocking(actor)
244//!         .perform()
245//!         .await.unwrap();
246//!
247//!     println!("Response: {:?}", response);
248//!
249//!     handle.abort();
250//! }
251//! ```
252//!
253//! ## Uploading a File with upload speed information sent to different task
254//! ```rust,no_run
255//! use std::{fs, path::PathBuf};
256//!
257//! use async_curl::CurlActor;
258//! use curl_http_client::*;
259//! use http::{HeaderMap, Method, Request};
260//! use tokio::sync::mpsc::channel;
261//! use url::Url;
262//!
263//! #[tokio::main(flavor = "current_thread")]
264//! async fn main() {
265//!     let (tx, mut rx) = channel(1);
266//!
267//!     let file_to_be_uploaded = PathBuf::from("<FILE PATH TO BE UPLOADED>");
268//!     let file_size = fs::metadata(file_to_be_uploaded.as_path()).unwrap().len() as usize;
269//!
270//!     let actor = CurlActor::new();
271//!     let file_info = FileInfo::path(file_to_be_uploaded).with_transfer_speed_sender(tx);
272//!     let collector = Collector::File(file_info);
273//!
274//!     let handle = tokio::spawn(async move {
275//!         while let Some(speed) = rx.recv().await {
276//!             println!("Upload Speed: {} kB/s", speed.as_bytes_per_sec());
277//!         }
278//!     });
279//!
280//!     let request = Request::builder()
281//!         .uri("<TARGET URL>")
282//!         .method(Method::PUT)
283//!         .body(None)
284//!         .unwrap();
285//!
286//!     let response = HttpClient::new(collector)
287//!         .upload_file_size(FileSize::from(file_size)).unwrap()
288//!         .request(request).unwrap()
289//!         .nonblocking(actor)
290//!         .perform()
291//!         .await.unwrap();
292//!
293//!     println!("Response: {:?}", response);
294//!     handle.abort();
295//! }
296//! ```
297//!
298//! # Synchronous Examples
299//! ## Get Request
300//! ```rust,no_run
301//! use curl_http_client::*;
302//! use http::{HeaderMap, Method, Request};
303//! use url::Url;
304//!
305//! let collector = Collector::Ram(Vec::new());
306//!
307//! let request = Request::builder()
308//!     .uri("<SOURCE URL>")
309//!     .method(Method::GET)
310//!     .body(None)
311//!     .unwrap();
312//!
313//! let response = HttpClient::new(collector)
314//!     .request(request).unwrap()
315//!     .blocking()
316//!     .perform()
317//!     .unwrap();
318//!
319//! println!("Response: {:?}", response);
320//! ```
321//!
322//! ## Post Request
323//! ```rust,no_run
324//! use curl_http_client::*;
325//! use http::{HeaderMap, Method, Request};
326//! use url::Url;
327//!
328//! let collector = Collector::Ram(Vec::new());
329//!
330//! let request = Request::builder()
331//!     .uri("<TARGET URL>")
332//!     .method(Method::POST)
333//!     .body(Some("test body".as_bytes().to_vec()))
334//!     .unwrap();
335//!
336//! let response = HttpClient::new(collector)
337//!     .request(request).unwrap()
338//!     .blocking()
339//!     .perform()
340//!     .unwrap();
341//!
342//! println!("Response: {:?}", response);
343//! ```
344//!
345//! ## Downloading a File
346//! ```rust,no_run
347//! use std::path::PathBuf;
348//!
349//! use curl_http_client::*;
350//! use http::{HeaderMap, Method, Request};
351//! use url::Url;
352//!
353//! let collector = Collector::File(FileInfo::path(PathBuf::from("<FILE PATH TO SAVE>")));
354//!
355//! let request = Request::builder()
356//!     .uri("<SOURCE URL>")
357//!     .method(Method::GET)
358//!     .body(None)
359//!     .unwrap();
360//!
361//! let response = HttpClient::new(collector)
362//!     .request(request)
363//!     .unwrap()
364//!     .blocking()
365//!     .perform()
366//!     .unwrap();
367//!
368//! println!("Response: {:?}", response);
369//! ```
370//!
371//! ## Uploading a File
372//! ```rust,no_run
373//! use std::{fs, path::PathBuf};
374//!
375//! use curl_http_client::*;
376//! use http::{HeaderMap, Method, Request};
377//! use url::Url;
378//!
379//! let file_to_be_uploaded = PathBuf::from("<FILE PATH TO BE UPLOADED>");
380//! let file_size = fs::metadata(file_to_be_uploaded.as_path()).unwrap().len() as usize;
381//! let collector = Collector::File(FileInfo::path(file_to_be_uploaded));
382//!
383//! let request = Request::builder()
384//!     .uri("<TARGET URL>")
385//!     .method(Method::PUT)
386//!     .body(None)
387//!     .unwrap();
388//!
389//! let response = HttpClient::new(collector)
390//!     .upload_file_size(FileSize::from(file_size)).unwrap()
391//!     .request(request).unwrap()
392//!     .blocking()
393//!     .perform()
394//!     .unwrap();
395//!
396//! println!("Response: {:?}", response);
397//! ```
398//!
399pub mod collector;
400pub mod error;
401pub mod http_client;
402
403pub mod dep {
404    pub use async_curl;
405    pub use curl;
406}
407
408#[cfg(test)]
409mod test;
410
411pub use collector::*;
412pub use error::*;
413pub use http_client::*;