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::*;