Call an API
Recipe | Crates | Categories |
---|---|---|
Query the GitHub API | ||
Check if an API Resource Exists | ||
Create and Delete a Gist with the GitHub API | ||
Consume a Paginated RESTful API | ||
Handle a Rate-limited API |
Query the GitHub API
Queries GitHub stargazers API v3⮳ with reqwest::get
⮳ to get list of all users who have marked a GitHub project with a star. reqwest::Response
⮳ is deserialized with reqwest::Response::json
⮳ into User
objects implementing serde::Deserialize
⮳.
tokio::main
is used to set up the async executor and the process waits for reqwest::get
to complete before processing the response into User instances.
use reqwest::Error; use serde::Deserialize; #[derive(Deserialize, Debug)] struct User { login: String, id: u32, } #[tokio::main] async fn main() -> Result<(), Error> { let request_url = format!( "https://api.github.com/repos/{owner}/{repo}/stargazers", owner = "john-cd", repo = "rust_howto" ); println!("{}", request_url); let client = reqwest::Client::builder().user_agent("Rust-test").build()?; let response = client.get(&request_url).send().await?; let users: Vec<User> = response.json().await?; println!("{:?}", users); Ok(()) }
Check if an API Resource Exists
Query the GitHub Users Endpoint using a HEAD request reqwest::Client::head
⮳ and then inspect the response code to determine success. This is a quick way to query a rest resource without needing to receive a body. reqwest::Client
⮳ configured with reqwest::ClientBuilder::timeout
⮳ ensures a request will not last longer than a timeout.
Due to both reqwest::ClientBuilder::build
⮳ and reqwest::RequestBuilder::send
⮳ returning reqwest::Error
⮳ types, the shortcut reqwest::Result
⮳ is used for the main function return type.
use std::time::Duration; use reqwest::ClientBuilder; #[tokio::main] async fn main() -> reqwest::Result<()> { let user = "ferris-the-crab"; let request_url = format!("https://api.github.com/users/{}", user); println!("{}", request_url); let timeout = Duration::new(5, 0); let client = ClientBuilder::new().timeout(timeout).build()?; let response = client.head(&request_url).send().await?; if response.status().is_success() { println!("{} is a user!", user); } else { println!("{} is not a user!", user); } Ok(()) }
Create and Delete a Gist with the GitHub API
Creates a gist with POST request to GitHub gists API v3⮳ using reqwest::Client::post
⮳ and removes it with DELETE request using reqwest::Client::post
⮳.
The reqwest::Client
⮳ is responsible for details of both requests including URL, body and authentication. The POST body from reqwest::Client
⮳ macro provides arbitrary JSON body. Call to reqwest::Client
⮳ sets the request body. reqwest::Client
⮳ handles authentication. The call to reqwest::Client
⮳ synchronously executes the requests.
use std::collections::HashMap; use std::env; use anyhow::Result; use reqwest::Client; use serde::Deserialize; use serde::Serialize; #[derive(Deserialize, Serialize, Debug)] struct Post<'a> { description: &'a str, public: bool, files: HashMap<&'a str, Content<'a>>, } #[derive(Deserialize, Serialize, Debug)] struct Content<'a> { content: &'a str, } #[derive(Deserialize, Debug)] struct Gist { id: String, html_url: String, } #[tokio::main] async fn main() -> Result<()> { let gh_user = env::var("GH_USER")?; let gh_pass = env::var("GH_PASS")?; // Example POST to the GitHub gists API let gist_body = Post { description: "the description for this gist", public: true, files: { let mut h = HashMap::new(); h.insert( "main.rs", Content { content: r#" fn main() { println!("hello world!");} "#, }, ); h }, }; let request_url = "https://api.github.com/gists"; let response = Client::new() .post(request_url) .basic_auth(gh_user.clone(), Some(gh_pass.clone())) .json(&gist_body) .send() .await?; let gist: Gist = response.json().await?; println!("Created {:?}", gist); let request_url = format!("{}/{}", request_url, gist.id); let response = Client::new() .delete(&request_url) .basic_auth(gh_user, Some(gh_pass)) .send() .await?; println!( "Gist {} deleted! Status code: {}", gist.id, response.status() ); Ok(()) }
The example uses HTTP basic auth
⮳ in order to authorize access to GitHub API
⮳. Typical use case would employ one of the much more complex OAuth
⮳ authorization flows.
Consume a Paginated RESTful API
Wraps a paginated web API in a convenient Rust iterator. The iterator lazily fetches the next page of results from the remote server as it arrives at the end of each page.
// // COMING SOON
Handle a Rate-limited API
This example uses the GitHub API - rate limiting
⮳, as an example of how to handle remote server errors. This example checks for reqwest::StatusCode::FORBIDDEN
⮳ If the response exceeds the rate limit, the example waits and retries.
// // COMING SOON