mirror of
https://github.com/rust-lang-nursery/rust-cookbook
synced 2024-11-22 03:23:05 +00:00
Adds example of handle a rate-limited API #93
This commit is contained in:
parent
29dacc6267
commit
2d3679b14e
2 changed files with 84 additions and 0 deletions
|
@ -109,6 +109,7 @@ community. It needs and welcomes help. For details see
|
|||
| [Check webpage for broken links][ex-check-broken-links] | [![reqwest-badge]][reqwest] [![select-badge]][select] [![url-badge]][url] | [![cat-net-badge]][cat-net] |
|
||||
| [Extract all unique links from a MediaWiki markup][ex-extract-mediawiki-links] | [![reqwest-badge]][reqwest] [![regex-badge]][regex] | [![cat-net-badge]][cat-net] |
|
||||
| [Make a partial download with HTTP range headers][ex-progress-with-range] | [![reqwest-badge]][reqwest] | [![cat-net-badge]][cat-net] |
|
||||
| [Handle a rate-limited API][ex-handle-rate-limited-api] | [![reqwest-badge]][reqwest] [![hyper-badge]][hyper] | [![cat-net-badge]][cat-net] |
|
||||
|
||||
## [Application development](app.html)
|
||||
|
||||
|
@ -263,3 +264,4 @@ community. It needs and welcomes help. For details see
|
|||
[ex-url-rm-frag]: net.html#ex-url-rm-frag
|
||||
[ex-urlencoded]: encoding.html#ex-urlencoded
|
||||
[ex-verify-extract-email]: basics.html#ex-verify-extract-email
|
||||
[ex-handle-rate-limited-api]: net.html#ex-handle-rate-limited-api
|
82
src/net.md
82
src/net.md
|
@ -20,6 +20,7 @@
|
|||
| [Check webpage for broken links][ex-check-broken-links] | [![reqwest-badge]][reqwest] [![select-badge]][select] [![url-badge]][url] | [![cat-net-badge]][cat-net] |
|
||||
| [Extract all unique links from a MediaWiki markup][ex-extract-mediawiki-links] | [![reqwest-badge]][reqwest] [![regex-badge]][regex] | [![cat-net-badge]][cat-net] |
|
||||
| [Make a partial download with HTTP range headers][ex-progress-with-range] | [![reqwest-badge]][reqwest] | [![cat-net-badge]][cat-net] |
|
||||
| [Handle a rate-limited API][ex-handle-rate-limited-api] | [![reqwest-badge]][reqwest] [![hyper-badge]][hyper] | [![cat-net-badge]][cat-net] |
|
||||
|
||||
[ex-url-parse]: #ex-url-parse
|
||||
<a name="ex-url-parse"/>
|
||||
|
@ -1120,6 +1121,85 @@ fn run() -> Result<()> {
|
|||
# quick_main!(run);
|
||||
```
|
||||
|
||||
[ex-handle-rate-limited-api]: #ex-handle-rate-limited-api
|
||||
<a name="ex-handle-rate-limited-api"/>
|
||||
## Handle a rate-limited API
|
||||
|
||||
[![reqwest-badge]][reqwest] [![hyper-badge]][hyper] [![cat-net-badge]][cat-net]
|
||||
|
||||
This example uses the [GitHub API - Rate limiting], as an example of how to
|
||||
handle remote server errors. This example uses the [`hyper::header!`] macro
|
||||
to parse the response header and checks for [`reqwest::StatusCode::Forbidden`].
|
||||
If the response exceeds the rate limit, the example waits and retries.
|
||||
|
||||
```rust,no_run
|
||||
#[macro_use]
|
||||
extern crate error_chain;
|
||||
#[macro_use]
|
||||
extern crate hyper;
|
||||
extern crate reqwest;
|
||||
|
||||
use std::time::{Duration, UNIX_EPOCH};
|
||||
use std::thread;
|
||||
use reqwest::StatusCode;
|
||||
#
|
||||
# error_chain! {
|
||||
# errors {
|
||||
# RateLimitExceded(quote: usize, lease_secs: u64) {
|
||||
# description("rate limit exceeded")
|
||||
# display("rate limit exceeded the {} calls, the next call will be allowed within {} seconds", quote, lease_secs)
|
||||
# }
|
||||
# }
|
||||
# foreign_links {
|
||||
# Io(std::io::Error);
|
||||
# Time(std::time::SystemTimeError);
|
||||
# Reqwest(reqwest::Error);
|
||||
# }
|
||||
# }
|
||||
|
||||
header! { (XRateLimitLimit, "X-RateLimit-Limit") => [usize] }
|
||||
header! { (XRateLimitRemaining, "X-RateLimit-Remaining") => [usize] }
|
||||
header! { (XRateLimitReset, "X-RateLimit-Reset") => [u64] }
|
||||
|
||||
fn run() -> Result<()> {
|
||||
let url = "https://api.github.com/users/rust-lang-nursery ";
|
||||
let client = reqwest::Client::new();
|
||||
let response = client.get(url).send()?;
|
||||
|
||||
let rate_limit = response.headers().get::<XRateLimitLimit>().ok_or(
|
||||
"response doesn't include the expected X-RateLimit-Limit header",
|
||||
)?;
|
||||
|
||||
let rate_remaining = response.headers().get::<XRateLimitRemaining>().ok_or(
|
||||
"response doesn't include the expected X-RateLimit-Remaining header",
|
||||
)?;
|
||||
|
||||
let rate_reset_at = response.headers().get::<XRateLimitReset>().ok_or(
|
||||
"response doesn't include the expected X-RateLimit-Reset header",
|
||||
)?;
|
||||
|
||||
let rate_reset_within = Duration::from_secs(**rate_reset_at) - UNIX_EPOCH.elapsed()?;
|
||||
|
||||
if response.status() == StatusCode::Forbidden && **rate_remaining == 0 {
|
||||
println!("Sleeping for {} seconds.", rate_reset_within.as_secs());
|
||||
thread::sleep(rate_reset_within);
|
||||
let _ = run();
|
||||
}
|
||||
else {
|
||||
println!(
|
||||
"Rate limit is currently {}/{}, the reset of this limit will be within {} seconds.",
|
||||
**rate_remaining,
|
||||
**rate_limit,
|
||||
rate_reset_within.as_secs(),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
#
|
||||
# quick_main!(run);
|
||||
```
|
||||
|
||||
{{#include links.md}}
|
||||
|
||||
<!-- API Reference -->
|
||||
|
@ -1158,6 +1238,7 @@ fn run() -> Result<()> {
|
|||
[`reqwest::header::Range`]: https://docs.rs/reqwest/*/reqwest/header/enum.Range.html
|
||||
[`reqwest::RequestBuilder`]: https://docs.rs/reqwest/*/reqwest/struct.RequestBuilder.html
|
||||
[`reqwest::Response`]: https://docs.rs/reqwest/*/reqwest/struct.Response.html
|
||||
[`reqwest::StatusCode::Forbidden`]: https://docs.rs/reqwest/*/reqwest/enum.StatusCode.html#variant.Forbidden
|
||||
[`Response::json`]: https://docs.rs/reqwest/*/reqwest/struct.Response.html#method.json
|
||||
[`Response::url`]: https://docs.rs/reqwest/*/reqwest/struct.Response.html#method.url
|
||||
[`Selection`]: https://docs.rs/select/*/select/selection/struct.Selection.html
|
||||
|
@ -1181,6 +1262,7 @@ fn run() -> Result<()> {
|
|||
<!-- Other Reference -->
|
||||
|
||||
[GitHub API]: https://developer.github.com/v3/auth/
|
||||
[GitHub API - Rate limiting]: https://developer.github.com/v3/#rate-limiting
|
||||
[HTTP Basic Auth]: https://tools.ietf.org/html/rfc2617
|
||||
[HTTP Range RFC7233]: https://tools.ietf.org/html/rfc7233#section-3.1
|
||||
[MediaWiki link syntax]: https://www.mediawiki.org/wiki/Help:Links
|
||||
|
|
Loading…
Reference in a new issue