Skip to content

Commit

Permalink
Improved examples
Browse files Browse the repository at this point in the history
  • Loading branch information
SfietKonstantin committed Feb 17, 2023
1 parent 6146738 commit 9ff80b3
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 30 deletions.
23 changes: 18 additions & 5 deletions pretend/examples/interceptor.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use pretend::http::header::AUTHORIZATION;
use pretend::http::HeaderValue;
use pretend::interceptor::{InterceptRequest, Request};
use pretend::{pretend, Pretend, Result, Url};
use pretend::{pretend, Error, Pretend, Result, Url};
use pretend_reqwest::Client;

// This example show how to use an interceptor to override headers
Expand All @@ -11,12 +12,24 @@ trait HttpBin {
async fn get(&self) -> Result<String>;
}

struct AuthInterceptor;
struct AuthInterceptor {
auth: String,
}

impl AuthInterceptor {
fn new(auth: String) -> Self {
AuthInterceptor { auth }
}
}

impl InterceptRequest for AuthInterceptor {
fn intercept(&self, mut request: Request) -> Result<Request> {
let value = HeaderValue::from_static("Bearer abcde");
request.headers.append("Authorization", value);
// Create the header, reporting failure if the header is invalid
let header = format!("Bearer {}", self.auth);
let header = HeaderValue::from_str(&header).map_err(|err| Error::Request(Box::new(err)))?;

// Set the authorization header in the request
request.headers.append(AUTHORIZATION, header);
Ok(request)
}
}
Expand All @@ -25,7 +38,7 @@ fn create_pretend() -> impl HttpBin {
let url = Url::parse("https://httpbin.org").unwrap();
Pretend::for_client(Client::default())
.with_url(url)
.with_request_interceptor(AuthInterceptor)
.with_request_interceptor(AuthInterceptor::new("test".to_string()))
}

#[tokio::main]
Expand Down
2 changes: 1 addition & 1 deletion pretend/src/interceptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! it is being executed.
//!
//! Interceptors can facilitate setting common headers, like
//! an user-agent, or injecting an authentication token.
//! an user-agent, or injecting an authentication token.
//!
//! By default a [`NoopRequestInterceptor`] is used, and will
//! not modify the request.
Expand Down
109 changes: 85 additions & 24 deletions pretend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,19 +131,19 @@
//! #[pretend]
//! trait HttpBin {
//! #[request(method = "POST", path = "/anything")]
//! async fn read_bytes(&self) -> Result<Vec<u8>>;
//! async fn get_bytes(&self) -> Result<Vec<u8>>;
//!
//! #[request(method = "POST", path = "/anything")]
//! async fn read_string(&self) -> Result<String>;
//! async fn get_string(&self) -> Result<String>;
//!
//! #[request(method = "POST", path = "/anything")]
//! async fn read_json(&self) -> Result<Json<Data>>;
//! async fn get_json(&self) -> Result<Json<Data>>;
//!
//! #[request(method = "POST", path = "/anything")]
//! async fn read_json_result(&self) -> Result<JsonResult<Data, Error>>;
//! async fn get_json_result(&self) -> Result<JsonResult<Data, Error>>;
//!
//! #[request(method = "POST", path = "/anything")]
//! async fn read_status(&self) -> Result<Response<()>>;
//! async fn get_status(&self) -> Result<Response<()>>;
//! }
//! ```
//!
Expand All @@ -154,11 +154,10 @@
//! any type that implement `Display` is supported.
//!
//! ```rust
//! use pretend::{pretend, Json, Pretend, Result};
//! use pretend::{pretend, Json, Pretend, Result, Url};
//! use pretend_reqwest::Client;
//! use serde::Deserialize;
//! use std::collections::HashMap;
//! # use pretend::Url;
//!
//! #[derive(Deserialize)]
//! struct Data {
Expand All @@ -170,27 +169,100 @@
//! trait HttpBin {
//! #[request(method = "POST", path = "/{path}")]
//! #[header(name = "X-{header}", value = "{value}$")]
//! async fn read(&self, path: &str, header: &str, value: i32) -> Result<Json<Data>>;
//! async fn get(&self, path: &str, header: &str, value: i32) -> Result<Json<Data>>;
//! }
//!
//! # #[tokio::main]
//! # async fn main() {
//! let client = Client::default();
//! let url = Url::parse("https://httpbin.org").unwrap();
//! let pretend = Pretend::for_client(client).with_url(url);
//! let response = pretend.read("anything", "My-Header", 123).await.unwrap();
//! let response = pretend.get("anything", "My-Header", 123).await.unwrap();
//! let data = response.value();
//! assert_eq!(data.url, "https://httpbin.org/anything");
//! assert_eq!(*data.headers.get("X-My-Header").unwrap(), "123$".to_string());
//! # }
//! ```
//!
//! # URL resolvers
//!
//! `pretend` uses URL resolvers to resolve a full URL from the path in `request`. By default
//! the URL resolver will simply append the path to a base URL. More advanced resolvers can
//! be implemented with the [resolver] module.
//!
//! # Request interceptors
//!
//! `pretend` uses request interceptors to customize auto-generated requests. They can be useful
//! when dealing with authentication. They can be implemented with the [interceptor] module.
//!
//! ```rust
//! use pretend::http::header::AUTHORIZATION;
//! use pretend::http::HeaderValue;
//! use pretend::interceptor::{InterceptRequest, Request};
//! use pretend::{pretend, Error, Json, Pretend, Result, Url};
//! use pretend_reqwest::Client;
//! use serde::Deserialize;
//! use std::collections::HashMap;
//!
//! #[derive(Deserialize)]
//! struct Data {
//! url: String,
//! headers: HashMap<String, String>,
//! }
//!
//! #[pretend]
//! trait HttpBin {
//! #[request(method = "GET", path = "/get")]
//! async fn get(&self) -> Result<Json<Data>>;
//! }
//!
//! struct AuthInterceptor {
//! auth: String,
//! }
//!
//! impl AuthInterceptor {
//! fn new(auth: String) -> Self {
//! AuthInterceptor { auth }
//! }
//! }
//!
//! impl InterceptRequest for AuthInterceptor {
//! fn intercept(&self, mut request: Request) -> Result<Request> {
//! // Create the header, reporting failure if the header is invalid
//! let header = format!("Bearer {}", self.auth);
//! let header = HeaderValue::from_str(&header).map_err(|err| Error::Request(Box::new(err)))?;
//!
//! // Set the authorization header in the request
//! request.headers.append(AUTHORIZATION, header);
//! Ok(request)
//! }
//! }
//! # #[tokio::main]
//! # async fn main() {
//! let client = Client::default();
//! let url = Url::parse("https://httpbin.org").unwrap();
//! let auth_interceptor = AuthInterceptor::new("test".to_string());
//! let pretend = Pretend::for_client(client).with_url(url).with_request_interceptor(auth_interceptor);
//! let response = pretend.get().await.unwrap();
//! let data = response.value();
//! assert_eq!(*data.headers.get("Authorization").unwrap(), "Bearer test".to_string());
//! # }
//! ```
//!
//! # Examples
//!
//! More examples are available in the [examples folder].
//!
//! [examples folder]: https://github.com/SfietKonstantin/pretend/tree/main/pretend/examples
//!
//! # Blocking requests
//!
//! When all methods in the `pretend`-annotated trait are async, `pretend` will generate
//! an async implementation. To generate a blocking implementation, simply remove the `async`.
//! an async implementation. To generate a blocking implementation, simply remove the `async`
//! keyword.
//!
//! Blocking implementations will need a blocking client implementation.
//! Blocking implementations needs a blocking client implementation to be used. In the following
//! example, we are using one provided by [`reqwest`]
//!
//! ```rust
//! use pretend::{pretend, Pretend, Result, Url};
Expand All @@ -211,14 +283,15 @@
//! # }
//! ```
//!
//! [`reqwest`]: https://crates.io/crates/pretend-reqwest
//!
//! # Non-Send implementation
//!
//! Today, Rust does not support futures in traits. `pretend` uses `async_trait` to workaround
//! that limitation. By default, `async_trait` adds the `Send` bound to futures. This implies
//! that `Pretend` itself is `Send` and `Sync`, and implies that the client implementation it uses
//! is also `Send` and `Sync`.
//!
//!
//! However, some clients are not thread-safe, and cannot be shared between threads. To use
//! these clients with `Pretend`, you have to opt-out from the `Send` constraint on returned
//! futures by using `#[pretend(?Send)]`. This is similar to what is done in [`async_trait`].
Expand Down Expand Up @@ -279,18 +352,6 @@
//! HTTP requests. See the [client] module level documentation for more information about
//! how to implement a client.
//!
//! # URL resolvers
//!
//! `pretend` uses URL resolvers to resolve a full URL from the path in `request`. By default
//! the URL resolver will simply append the path to a base URL. More advanced resolvers can
//! be implemented with the [resolver] module.
//!
//! # Examples
//!
//! More examples are available in the [examples folder].
//!
//! [examples folder]: https://github.com/SfietKonstantin/pretend/tree/main/pretend/examples
//!
//! # MSRV
//!
//! MSRV for the `pretend` ecosystem is Rust **1.44**.
Expand Down

0 comments on commit 9ff80b3

Please sign in to comment.