Skip to content

Commit

Permalink
feat: support both sync and async curl transactions
Browse files Browse the repository at this point in the history
There is a slight change in the builder pattern so that we
could be able to use this crate dynamically both sync and async
transactions for Curl rust.
  • Loading branch information
LorenzoLeonardo committed Feb 17, 2024
1 parent 1a2734a commit 39cf4ac
Show file tree
Hide file tree
Showing 15 changed files with 603 additions and 114 deletions.
168 changes: 150 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
# curl-http-client

This is a wrapper for Easy2 from curl-rust crate for ergonomic use
and is able to perform asynchronously using async-curl crate
and is able to perform synchronously and asynchronously using async-curl crate
that uses an actor model (Message passing) to achieve a non-blocking I/O.

[![Latest Version](https://img.shields.io/crates/v/curl-http-client.svg)](https://crates.io/crates/curl-http-client)
[![License](https://img.shields.io/github/license/LorenzoLeonardo/curl-http-client.svg)](LICENSE-MIT)
[![Documentation](https://docs.rs/curl-http-client/badge.svg)](https://docs.rs/curl-http-client)
[![Build Status](https://github.com/LorenzoLeonardo/curl-http-client/workflows/Rust/badge.svg)](https://github.com/LorenzoLeonardo/curl-http-client/actions)

# Asynchronous Examples

## Get Request
```rust
use async_curl::actor::CurlActor;
Expand All @@ -18,7 +20,7 @@ use url::Url;

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let curl = CurlActor::new();
let actor = CurlActor::new();
let collector = Collector::Ram(Vec::new());

let request = HttpRequest {
Expand All @@ -28,8 +30,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
body: None,
};

let response = HttpClient::new(curl, collector)
let response = HttpClient::new(collector)
.request(request)?
.nonblocking(actor)
.perform()
.await?;

Expand All @@ -47,7 +50,7 @@ use url::Url;

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let curl = CurlActor::new();
let actor = CurlActor::new();
let collector = Collector::Ram(Vec::new());

let request = HttpRequest {
Expand All @@ -57,8 +60,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
body: Some("test body".as_bytes().to_vec()),
};

let response = HttpClient::new(curl, collector)
let response = HttpClient::new(collector)
.request(request)?
.nonblocking(actor)
.perform()
.await?;

Expand All @@ -82,7 +86,7 @@ use url::Url;

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let curl = CurlActor::new();
let actor = CurlActor::new();

let collector = Collector::File(FileInfo::path(PathBuf::from("<FILE PATH TO SAVE>")));

Expand All @@ -93,8 +97,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
body: None,
};

let response = HttpClient::new(curl, collector)
let response = HttpClient::new(collector)
.request(request)?
.nonblocking(actor)
.perform()
.await?;

Expand All @@ -121,7 +126,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let file_to_be_uploaded = PathBuf::from("<FILE PATH TO BE UPLOADED>");
let file_size = fs::metadata(file_to_be_uploaded.as_path()).unwrap().len() as usize;

let curl = CurlActor::new();
let actor = CurlActor::new();
let collector = Collector::File(FileInfo::path(file_to_be_uploaded));

let request = HttpRequest {
Expand All @@ -131,9 +136,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
body: None,
};

let response = HttpClient::new(curl, collector)
let response = HttpClient::new(collector)
.upload_file_size(FileSize::from(file_size))?
.request(request)?
.nonblocking(actor)
.perform()
.await?;

Expand All @@ -154,11 +160,11 @@ use url::Url;
async fn main() {
const NUM_CONCURRENT: usize = 5;

let curl = CurlActor::new();
let actor = CurlActor::new();
let mut handles = Vec::new();

for _n in 0..NUM_CONCURRENT {
let curl = curl.clone();
let actor = actor.clone();

let handle = tokio::spawn(async move {
let collector = Collector::Ram(Vec::new());
Expand All @@ -169,9 +175,10 @@ async fn main() {
body: None,
};

let response = HttpClient::new(curl, collector)
let response = HttpClient::new(collector)
.request(request)
.unwrap()
.nonblocking(actor)
.perform()
.await
.unwrap();
Expand Down Expand Up @@ -204,7 +211,7 @@ use url::Url;

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let curl = CurlActor::new();
let actor = CurlActor::new();
let save_to = PathBuf::from("<FILE PATH TO SAVE>");
let collector = Collector::File(FileInfo::path(save_to.clone()));

Expand All @@ -216,9 +223,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
body: None,
};

let response = HttpClient::new(curl, collector)
let response = HttpClient::new(collector)
.resume_from(BytesOffset::from(partial_download_file_size))?
.request(request)?
.nonblocking(actor)
.perform()
.await?;
println!("Response: {:?}", response);
Expand All @@ -244,7 +252,7 @@ use url::Url;
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let (tx, mut rx) = channel(1);

let curl = CurlActor::new();
let actor = CurlActor::new();
let file_info = FileInfo::path(PathBuf::from("<FILE PATH TO SAVE>")).with_transfer_speed_sender(tx);
let collector = Collector::File(file_info);

Expand All @@ -261,8 +269,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
body: None,
};

let response = HttpClient::new(curl, collector)
let response = HttpClient::new(collector)
.request(request)?
.nonblocking(actor)
.perform()
.await?;

Expand Down Expand Up @@ -294,7 +303,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let file_to_be_uploaded = PathBuf::from("<FILE PATH TO BE UPLOADED>");
let file_size = fs::metadata(file_to_be_uploaded.as_path()).unwrap().len() as usize;

let curl = CurlActor::new();
let actor = CurlActor::new();
let file_info = FileInfo::path(file_to_be_uploaded).with_transfer_speed_sender(tx);
let collector = Collector::File(file_info);

Expand All @@ -311,14 +320,137 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
body: None,
};

let response = HttpClient::new(curl, collector)
let response = HttpClient::new(collector)
.upload_file_size(FileSize::from(file_size))?
.request(request)?
.nonblocking(actor)
.perform()
.await?;

println!("Response: {:?}", response);
handle.abort();
Ok(())
}
```

# Synchronous Examples

## Get Request
```rust
use curl_http_client::{collector::Collector, http_client::HttpClient, request::HttpRequest};
use http::{HeaderMap, Method};
use url::Url;

fn main() -> Result<(), Box<dyn std::error::Error>> {
let collector = Collector::Ram(Vec::new());

let request = HttpRequest {
url: Url::parse("<SOURCE URL>")?,
method: Method::GET,
headers: HeaderMap::new(),
body: None,
};

let response = HttpClient::new(collector)
.request(request)?
.blocking()
.perform()?;

println!("Response: {:?}", response);
Ok(())
}
```

## Post Request
```rust
use curl_http_client::{collector::Collector, http_client::HttpClient, request::HttpRequest};
use http::{HeaderMap, Method};
use url::Url;

fn main() -> Result<(), Box<dyn std::error::Error>> {
let collector = Collector::Ram(Vec::new());

let request = HttpRequest {
url: Url::parse("<TARGET URL>")?,
method: Method::POST,
headers: HeaderMap::new(),
body: Some("test body".as_bytes().to_vec()),
};

let response = HttpClient::new(collector)
.request(request)?
.blocking()
.perform()?;

println!("Response: {:?}", response);
Ok(())
}
```

## Downloading a File
```rust
use std::path::PathBuf;

use curl_http_client::{
collector::{Collector, FileInfo},
http_client::HttpClient,
request::HttpRequest,
};
use http::{HeaderMap, Method};
use url::Url;

fn main() -> Result<(), Box<dyn std::error::Error>> {
let collector = Collector::File(FileInfo::path(PathBuf::from("<FILE PATH TO SAVE>")));

let request = HttpRequest {
url: Url::parse("<SOURCE URL>")?,
method: Method::GET,
headers: HeaderMap::new(),
body: None,
};

let response = HttpClient::new(collector)
.request(request)?
.blocking(actor)
.perform()?;

println!("Response: {:?}", response);
Ok(())
}
```

## Uploading a File
```rust
use std::{fs, path::PathBuf};

use curl_http_client::{
collector::{Collector, FileInfo},
http_client::{FileSize, HttpClient},
request::HttpRequest,
};
use http::{HeaderMap, Method};
use url::Url;

fn main() -> Result<(), Box<dyn std::error::Error>> {
let file_to_be_uploaded = PathBuf::from("<FILE PATH TO BE UPLOADED>");
let file_size = fs::metadata(file_to_be_uploaded.as_path()).unwrap().len() as usize;

let collector = Collector::File(FileInfo::path(file_to_be_uploaded));

let request = HttpRequest {
url: Url::parse("<TARGET URL>")?,
method: Method::PUT,
headers: HeaderMap::new(),
body: None,
};

let response = HttpClient::new(collector)
.upload_file_size(FileSize::from(file_size))?
.request(request)?
.blocking()
.perform()?;

println!("Response: {:?}", response);
Ok(())
}
```
5 changes: 3 additions & 2 deletions examples/asynchronous.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async fn main() {
let mut handles = Vec::new();

for _n in 0..NUM_CONCURRENT {
let curl = curl.clone();
let actor = curl.clone();

let handle = tokio::spawn(async move {
let collector = Collector::Ram(Vec::new());
Expand All @@ -23,9 +23,10 @@ async fn main() {
body: None,
};

let response = HttpClient::new(curl, collector)
let response = HttpClient::new(collector)
.request(request)
.unwrap()
.nonblocking(actor)
.perform()
.await
.unwrap();
Expand Down
5 changes: 3 additions & 2 deletions examples/download.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use url::Url;

#[tokio::main(flavor = "current_thread")]
async fn main() {
let curl = CurlActor::new();
let actor = CurlActor::new();

let collector = Collector::File(FileInfo::path(PathBuf::from("<FILE PATH TO SAVE>")));

Expand All @@ -22,9 +22,10 @@ async fn main() {
body: None,
};

let response = HttpClient::new(curl, collector)
let response = HttpClient::new(collector)
.request(request)
.unwrap()
.nonblocking(actor)
.perform()
.await
.unwrap();
Expand Down
5 changes: 3 additions & 2 deletions examples/get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use url::Url;

#[tokio::main(flavor = "current_thread")]
async fn main() {
let curl = CurlActor::new();
let actor = CurlActor::new();
let collector = Collector::Ram(Vec::new());

let request = HttpRequest {
Expand All @@ -15,9 +15,10 @@ async fn main() {
body: None,
};

let response = HttpClient::new(curl, collector)
let response = HttpClient::new(collector)
.request(request)
.unwrap()
.nonblocking(actor)
.perform()
.await
.unwrap();
Expand Down
5 changes: 3 additions & 2 deletions examples/post.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use url::Url;

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let curl = CurlActor::new();
let actor = CurlActor::new();
let collector = Collector::Ram(Vec::new());

let request = HttpRequest {
Expand All @@ -15,9 +15,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
body: Some("test body".as_bytes().to_vec()),
};

let response = HttpClient::new(curl, collector)
let response = HttpClient::new(collector)
.request(request)
.unwrap()
.nonblocking(actor)
.perform()
.await
.unwrap();
Expand Down
Loading

0 comments on commit 39cf4ac

Please sign in to comment.