Skip to main content

Crate rate_limits

Crate rate_limits 

Source
Expand description

§rate-limits

docs.rs

A crate for parsing HTTP rate limit headers as per the IETF draft. Unofficial implementations like the Github rate limit headers are also supported, with vendor detection driven by exact (case-sensitive) header name matching for stronger disambiguation between APIs that share header names. APIs that aren’t explicitly listed still parse via a generic fallback on a best-effort basis. See vendor list for the set of recognized vendors.

The easiest way to use this crate is with http::HeaderMap (which is the standard used by reqwest, hyper, and axum).

use std::str::FromStr;
use time::OffsetDateTime;
use std::time::Duration;
use rate_limits::{Vendor, VendorMask, RateLimit, ResetTime, Headers};
use http::header::HeaderMap;

let mut headers = HeaderMap::new();
headers.insert("x-ratelimit-limit", "5000".parse().unwrap());
headers.insert("x-ratelimit-remaining", "4987".parse().unwrap());
headers.insert("x-ratelimit-reset", "1350085394".parse().unwrap());

// Because these headers are generic, the crate safely identifies multiple candidates
assert_eq!(
    RateLimit::new(&headers).unwrap(),
    RateLimit::Rfc6585(Headers {
        limit: 5000,
        remaining: 4987,
        reset: ResetTime::DateTime(
            OffsetDateTime::from_unix_timestamp(1350085394).unwrap()
        ),
        window: None,
        vendor: Vendor::Generic,
        candidates: VendorMask::from_iter([
            Vendor::Discord,
            Vendor::Github,
            Vendor::Twilio,
        ]),
    }),
);

§Unique Vendor Matching

If the API response includes highly specific “extra” headers, the state machine’s specificity scoring will identify the exact vendor.

You can parse rate limits directly from raw string iterators or via FromStr:

use indoc::indoc;
use std::str::FromStr;
use time::OffsetDateTime;
use std::time::Duration;
use rate_limits::{Vendor, VendorMask, RateLimit, ResetTime, Headers};

let headers = indoc! {"
    x-ratelimit-limit: 5000
    x-ratelimit-remaining: 4987
    x-ratelimit-reset: 1350085394
    x-ratelimit-used: 13
    x-ratelimit-resource: core
"};

// The parser observes that multiple vendors match the generic limit/remaining/reset headers 
// (which populate the `candidates` mask). However, the presence of `x-ratelimit-used` and 
// `x-ratelimit-resource` gives GitHub a higher specificity score, unambiguously identifying it 
// in the `vendor` field!
assert_eq!(
    RateLimit::from_str(headers).unwrap(),
    RateLimit::Rfc6585(Headers {
        limit: 5000,
        remaining: 4987,
        reset: ResetTime::DateTime(
            OffsetDateTime::from_unix_timestamp(1350085394).unwrap()
        ),
        window: Some(Duration::from_secs(3600)),
        vendor: Vendor::Github,
        candidates: VendorMask::from_iter([Vendor::Github]),
    }),
);

Also takes the Retry-After header into account when calculating the reset time.

§Further development

There is a new IETF draft which supersedes the old “polli” draft. It introduces a new RateLimit-Policy header which specifies the rate limit quota policy. The goal is to support this new draft in this crate as well.

§Other resources:

License: Apache-2.0/MIT

Re-exports§

pub use headers::Headers;

Modules§

headers
Rate limit headers as defined in RFC 6585 and [draft-polli-ratelimit-headers-00][draft].
retry_after
Retry-After header parsing

Structs§

VendorMask
A lightweight bitmask for tracking sets of candidate vendors without allocation.

Enums§

RateLimit
Rate Limit information, parsed from HTTP headers.
ResetTime
Reset time of rate limiting
Status
The status of the rate limit.
Vendor
Known vendors of rate limit headers