Skip to content

Commit

Permalink
Merge pull request #9 from SfietKonstantin/examples
Browse files Browse the repository at this point in the history
Added examples on how to use pretend
  • Loading branch information
SfietKonstantin authored May 12, 2021
2 parents edf18de + 0da5f8b commit df2204e
Show file tree
Hide file tree
Showing 8 changed files with 350 additions and 22 deletions.
80 changes: 80 additions & 0 deletions pretend/examples/bodies.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use pretend::{header, pretend, request, Pretend, Result, Serialize, Url};
use pretend_reqwest::Client as RClient;

// This example show how to send various body types to https://httpbin.org

#[derive(Clone, Serialize)]
struct Data {
first: String,
second: i32,
}

#[pretend]
trait HttpBin {
#[request(method = "POST", path = "/anything")]
#[header(name = "Content-Type", value = "text/plain")]
async fn post_string_ref(&self, body: &'static str) -> Result<String>;

#[request(method = "POST", path = "/anything")]
#[header(name = "Content-Type", value = "text/plain")]
async fn post_string(&self, body: String) -> Result<String>;

#[request(method = "POST", path = "/anything")]
#[header(name = "Content-Type", value = "application/octet-stream")]
async fn post_bytes_ref(&self, body: &'static [u8]) -> Result<String>;

#[request(method = "POST", path = "/anything")]
#[header(name = "Content-Type", value = "application/octet-stream")]
async fn post_bytes(&self, body: Vec<u8>) -> Result<String>;

#[request(method = "POST", path = "/anything")]
async fn post_form_ref(&self, form: &Data) -> Result<String>;

#[request(method = "POST", path = "/anything")]
async fn post_form(&self, form: Data) -> Result<String>;

#[request(method = "POST", path = "/anything")]
async fn post_json_ref(&self, json: &Data) -> Result<String>;

#[request(method = "POST", path = "/anything")]
async fn post_json(&self, json: Data) -> Result<String>;
}

fn create_pretend() -> impl HttpBin {
let url = Url::parse("https://httpbin.org").unwrap();
Pretend::for_client(RClient::default()).with_url(url)
}

#[tokio::main]
async fn main() {
let pretend = create_pretend();

let result = pretend.post_string_ref("Hello").await.unwrap();
println!("{}", result);

let result = pretend.post_string("Hello".to_string()).await.unwrap();
println!("{}", result);

let result = pretend.post_bytes_ref(&[1, 2, 3]).await.unwrap();
println!("{}", result);

let result = pretend.post_bytes(vec![1, 2, 3]).await.unwrap();
println!("{}", result);

let data = Data {
first: "Hello".to_string(),
second: 123,
};

let result = pretend.post_form_ref(&data).await.unwrap();
println!("{}", result);

let result = pretend.post_form(data.clone()).await.unwrap();
println!("{}", result);

let result = pretend.post_json_ref(&data).await.unwrap();
println!("{}", result);

let result = pretend.post_json(data.clone()).await.unwrap();
println!("{}", result);
}
25 changes: 25 additions & 0 deletions pretend/examples/headers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use pretend::{header, pretend, request, Pretend, Result, Url};
use pretend_reqwest::Client as RClient;

// This example show how to send various headers to https://httpbin.org

#[pretend]
trait HttpBin {
#[request(method = "GET", path = "/get")]
#[header(name = "X-Test", value = "Hello")]
#[header(name = "X-Something-Nice", value = "Lovely")]
async fn get(&self) -> Result<String>;
}

fn create_pretend() -> impl HttpBin {
let url = Url::parse("https://httpbin.org").unwrap();
Pretend::for_client(RClient::default()).with_url(url)
}

#[tokio::main]
async fn main() {
let pretend = create_pretend();

let result = pretend.get().await.unwrap();
println!("{}", result);
}
42 changes: 42 additions & 0 deletions pretend/examples/methods.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use pretend::{pretend, request, Pretend, Result, Url};
use pretend_reqwest::Client as RClient;

// This example show how to send HTTP requests to https://httpbin.org
// using different methods

#[pretend]
trait HttpBin {
#[request(method = "GET", path = "/get")]
async fn get(&self) -> Result<String>;

#[request(method = "POST", path = "/post")]
async fn post(&self) -> Result<String>;

#[request(method = "PUT", path = "/put")]
async fn put(&self) -> Result<String>;

#[request(method = "DELETE", path = "/delete")]
async fn delete(&self) -> Result<String>;
}

fn create_pretend() -> impl HttpBin {
let url = Url::parse("https://httpbin.org").unwrap();
Pretend::for_client(RClient::default()).with_url(url)
}

#[tokio::main]
async fn main() {
let pretend = create_pretend();

let get = pretend.get().await.unwrap();
println!("{}", get);

let post = pretend.post().await.unwrap();
println!("{}", post);

let put = pretend.post().await.unwrap();
println!("{}", put);

let delete = pretend.post().await.unwrap();
println!("{}", delete);
}
40 changes: 40 additions & 0 deletions pretend/examples/queries.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use pretend::{pretend, request, Pretend, Result, Serialize, Url};
use pretend_reqwest::Client as RClient;

// This example show how to pass URL queries to https://httpbin.org

#[derive(Clone, Serialize)]
struct Query {
first: String,
second: i32,
}

#[pretend]
trait HttpBin {
#[request(method = "GET", path = "/get?first={first}&second={second}")]
async fn get(&self, first: String, second: i32) -> Result<String>;

#[request(method = "GET", path = "/get")]
async fn get_query(&self, query: Query) -> Result<String>;
}

fn create_pretend() -> impl HttpBin {
let url = Url::parse("https://httpbin.org").unwrap();
Pretend::for_client(RClient::default()).with_url(url)
}

#[tokio::main]
async fn main() {
let pretend = create_pretend();

let result = pretend.get("Hello".to_string(), 123).await.unwrap();
println!("{}", result);

let query = Query {
first: "Hello".to_string(),
second: 123,
};

let result = pretend.get_query(query).await.unwrap();
println!("{}", result);
}
124 changes: 124 additions & 0 deletions pretend/examples/responses.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
use pretend::{
header, pretend, request, Deserialize, Json, JsonResult, Pretend, Response, Result, Url,
};
use pretend_reqwest::Client as RClient;

// This example show how to receive various response types.
// It uses the Github API (that returns JSON)

#[derive(Clone, Debug, Deserialize)]
struct Contributor {
login: String,
}

type Contributors = Vec<Contributor>;

#[derive(Clone, Debug, Deserialize)]
struct GithubError {
message: String,
}

type ContributorsResult = JsonResult<Contributors, GithubError>;

#[pretend]
trait Github {
#[request(method = "GET", path = "/repos/SfietKonstantin/{repo}/contributors")]
#[header(name = "User-Agent", value = "pretend example")]
async fn string(&self, repo: &str) -> Result<String>;

#[request(method = "GET", path = "/repos/SfietKonstantin/{repo}/contributors")]
#[header(name = "User-Agent", value = "pretend example")]
async fn string_response(&self, repo: &str) -> Result<Response<String>>;

#[request(method = "GET", path = "/repos/SfietKonstantin/{repo}/contributors")]
#[header(name = "User-Agent", value = "pretend example")]
async fn bytes(&self, repo: &str) -> Result<Vec<u8>>;

#[request(method = "GET", path = "/repos/SfietKonstantin/{repo}/contributors")]
#[header(name = "User-Agent", value = "pretend example")]
async fn bytes_response(&self, repo: &str) -> Result<Response<Vec<u8>>>;

#[request(method = "GET", path = "/repos/SfietKonstantin/{repo}/contributors")]
#[header(name = "User-Agent", value = "pretend example")]
async fn json(&self, repo: &str) -> Result<Json<Contributors>>;

#[request(method = "GET", path = "/repos/SfietKonstantin/{repo}/contributors")]
#[header(name = "User-Agent", value = "pretend example")]
async fn json_response(&self, repo: &str) -> Result<Response<Json<Contributors>>>;

#[request(method = "GET", path = "/repos/SfietKonstantin/{repo}/contributors")]
#[header(name = "User-Agent", value = "pretend example")]
async fn json_result(&self, repo: &str) -> Result<ContributorsResult>;

#[request(method = "GET", path = "/repos/SfietKonstantin/{repo}/contributors")]
#[header(name = "User-Agent", value = "pretend example")]
async fn json_result_response(&self, repo: &str) -> Result<Response<ContributorsResult>>;
}

fn create_pretend() -> impl Github {
let url = Url::parse("https://api.github.com").unwrap();
Pretend::for_client(RClient::default()).with_url(url)
}

#[tokio::main]
async fn main() {
let pretend = create_pretend();

// The following successful calls will return different kind of responses.
// Either bodies are return alone, or with status and headers by using Response.
let result = pretend.string("pretend").await.unwrap();
println!("{}", result);

let result = pretend.string_response("pretend").await.unwrap();
println!("HTTP {}, {}", result.status(), result.body());

let result = pretend.bytes("pretend").await.unwrap();
let body = String::from_utf8_lossy(&result);
println!("{}", body);

let result = pretend.bytes_response("pretend").await.unwrap();
let body = String::from_utf8_lossy(result.body());
println!("HTTP {}, {}", result.status(), body);

let result = pretend.json("pretend").await.unwrap();
println!("{:?}", result.value());

let result = pretend.json_response("pretend").await.unwrap();
println!("HTTP {}, {:?}", result.status(), result.body());

let result = pretend.json_result("pretend").await.unwrap();
println!("{:?}", result);

let result = pretend.json_result_response("pretend").await.unwrap();
println!("HTTP {}, {:?}", result.status(), result.body());

// The following calls will fail for a non-existing repo

// These calls fail on an error, as they only return a body when successful.
let result = pretend.string("non-existing").await;
assert!(result.is_err());

let result = pretend.bytes("non-existing").await;
assert!(result.is_err());

let result = pretend.json("non-existing").await;
assert!(result.is_err());

// These calls returns a Response. It is possible to inspect the status
// except for Json, as body deserialization will fail.
let result = pretend.string_response("non-existing").await.unwrap();
assert_eq!(result.status().as_u16(), 404);

let result = pretend.bytes_response("non-existing").await.unwrap();
assert_eq!(result.status().as_u16(), 404);

let result = pretend.json_response("non-existing").await;
assert!(result.is_err());

// By using JsonResult, a different body can be returned on error
let result = pretend.json_result("non-existing").await.unwrap();
println!("{:?}", result);

let result = pretend.json_result_response("non-existing").await.unwrap();
println!("HTTP {}, {:?}", result.status(), result.body());
}
19 changes: 0 additions & 19 deletions pretend/examples/simple_get.rs

This file was deleted.

35 changes: 35 additions & 0 deletions pretend/examples/templating.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use pretend::{header, pretend, request, Pretend, Result, Url};
use pretend_reqwest::Client as RClient;

// This example show how to use templating to customize paths and headers

#[pretend]
trait HttpBin {
#[request(method = "GET", path = "/{path}")]
#[header(name = "X-{header}", value = "{first}-{second}")]
#[header(name = "X-Test", value = "{value}")]
async fn get(
&self,
path: &str,
header: &str,
first: i32,
second: i32,
value: &str,
) -> Result<String>;
}

fn create_pretend() -> impl HttpBin {
let url = Url::parse("https://httpbin.org").unwrap();
Pretend::for_client(RClient::default()).with_url(url)
}

#[tokio::main]
async fn main() {
let pretend = create_pretend();

let result = pretend
.get("get", "Header", 1, 2, "something")
.await
.unwrap();
println!("{}", result);
}
7 changes: 4 additions & 3 deletions pretend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,15 +203,15 @@
//!
//! # Examples
//!
//! Please refer to the examples folder for more examples. There are not many examples yet, but
//! we are working on it !
//! More examples are available in the [examples folder].
//!
//! [examples folder]: https://github.com/SfietKonstantin/pretend/tree/main/pretend/examples
//!
//! # The future
//!
//! Here is a quick roadmap
//!
//! - Support more clients (awc)
//! - Write more examples
//! - Introduce more attributes to mark method parameters (body, json, params)
//! - Better error reporting
//! - Introduce interceptors
Expand Down Expand Up @@ -352,6 +352,7 @@ where
///
/// This wrapper type indicates that a method should return
/// a JSON-serialized body.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Json<T>
where
T: DeserializeOwned,
Expand Down

0 comments on commit df2204e

Please sign in to comment.