From 1a0ae872f5ec1b8727e1009db8bac2a0402b6d87 Mon Sep 17 00:00:00 2001 From: Mingwei Samuel Date: Sun, 19 Sep 2021 11:22:09 -0700 Subject: [PATCH] Add RiotApi::new(impl Into), deprecate old constructors, update docs - Adds `From> for RiotApiConfig` for API keys for the above. --- README.md | 36 +++++++++++++++++++++--------------- example/proxy/README.md | 13 ++++++++++--- example/proxy/src/main.rs | 3 +-- riven/src/config.rs | 12 +++++++++--- riven/src/lib.rs | 36 +++++++++++++++++++++--------------- riven/src/riot_api.rs | 37 +++++++++++++++++++++++++------------ riven/tests/testutils.rs | 3 +-- 7 files changed, 88 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 67becbe..5d41c3a 100644 --- a/README.md +++ b/README.md @@ -15,13 +15,13 @@ Riven's goals are _speed_, _reliability_, and _maintainability_. Riven handles r Data structs and endpoints are automatically generated from the [Riot API Reference](https://developer.riotgames.com/api-methods/) ([Swagger](http://www.mingweisamuel.com/riotapi-schema/tool/)). -## Design +# Design * Fast, asynchronous, thread-safe. * Automatically retries failed requests. * Supports all endpoints, kept up-to-date using [riotapi-schema](https://github.com/MingweiSamuel/riotapi-schema). -## Usage +# Usage ```rust use riven::RiotApi; @@ -32,7 +32,7 @@ let rt = tokio::runtime::Runtime::new().unwrap(); rt.block_on(async { // Create RiotApi instance from key string. let api_key = std::env!("RGAPI_KEY"); // "RGAPI-01234567-89ab-cdef-0123-456789abcdef"; - let riot_api = RiotApi::with_key(api_key); + let riot_api = RiotApi::new(api_key); // Get summoner data. let summoner = riot_api.summoner_v4() @@ -70,9 +70,14 @@ Output: 9) Irelia 46465 (5) 10) Vladimir 37176 (5) ``` -### Feature Flags +The [`RiotApi` struct documentation](https://docs.rs/riven/latest/riven/struct.RiotApi.html) +contains additional usage information. The [tests](https://github.com/MingweiSamuel/Riven/tree/v/2.x.x/riven/tests) +and [example proxy](https://github.com/MingweiSamuel/Riven/tree/v/2.x.x/example/proxy) +provide more example usage. -#### Nightly vs Stable +## Feature Flags + +### Nightly vs Stable Enable the `nightly` feature to use nightly-only functionality. This enables [nightly optimizations in the `parking_lot` crate](https://github.com/Amanieu/parking_lot#nightly-vs-stable). @@ -81,7 +86,7 @@ Enable the `nightly` feature to use nightly-only functionality. This enables riven = { version = "...", features = [ "nightly" ] } ``` -#### rustls +### rustls Riven uses [reqwest](https://github.com/seanmonstar/reqwest) for making requests. By default, reqwest uses the native TLS library. If you prefer using [rustls](https://github.com/ctz/rustls) you can do so by turning off the Riven default features @@ -93,11 +98,11 @@ riven = { version = "...", default-features = false, features = [ "rustls-tls" ] Riven is additionally able to produce [tracing](https://docs.rs/tracing) spans for requests if the `tracing` feature is enabled. This feature is disabled by default. -### Docs +## Docs [On docs.rs](https://docs.rs/riven/). -### Error Handling +## Error Handling Riven returns either `Result` or `Result>` within futures. @@ -116,12 +121,12 @@ diagnostic information, such as the source Reqwest error, the number of retries attempted, and the Reqwest `Response` object. You can configure the number of time Riven retries using -`RiotApiConfig::set_retries(...)` and the `RiotApi::with_config(config)` +`RiotApiConfig::set_retries(...)` and the `RiotApi::from_config(config)` constructor. By default, Riven retries up to 3 times (4 requests total). Some errors, such as 400 client errors, are not retried as they would inevitably fail again. -### Semantic Versioning +## Semantic Versioning This package follows semantic versioning to an extent. However, the Riot API itself changes often and does not follow semantic versioning, which makes @@ -137,21 +142,22 @@ not the major version. Parts of Riven that do not depend on Riot API changes do follow semantic versioning. -### Additional Help +## Additional Help Feel free to [make an issue](https://github.com/MingweiSamuel/Riven/issues/new) if you are have any questions or trouble with Riven. -## Development +# Development NodeJS is used to generate code for Riven. The -[`srcgen/`](https://github.com/MingweiSamuel/Riven/tree/v/2.x.x/riven/srcgen) +[`riven/srcgen`](https://github.com/MingweiSamuel/Riven/tree/v/2.x.x/riven/srcgen) folder contains the code and [doT.js](https://olado.github.io/doT/index.html) templates. `index.js` lists the JSON files downloaded and used to generate the code. To set up the srcgen, you will first need to install NodeJS. Then enter the -srcgen folder and run `npm ci` (or `npm install`) to install dependencies. +`riven/srcgen` folder and run `npm ci` (or `npm install`) to install +dependencies. -To run the srcgen use `node srcgen` from the main folder. +To run the srcgen use `node riven/srcgen` from the repository root. diff --git a/example/proxy/README.md b/example/proxy/README.md index 9cc0a45..3df8f46 100644 --- a/example/proxy/README.md +++ b/example/proxy/README.md @@ -1,8 +1,15 @@ # Riven Example Proxy -This is a simple example implementation of a Riot API proxy server using `hyper`. This adds the API key and forwards -requests to the Riot API, then returns and forwards responses back to the requester. It handles error cases but only -provides minimal failure information. HTTP requests will wait to complete when Riven is waiting on rate limits. +This is a simple example implementation of a Riot API proxy server using +[`hyper`](https://github.com/hyperium/hyper). This adds the API key and +forwards requests to the Riot API, then returns and forwards responses back to +the requester. + +This can handle not just GET endpoints but also POST and PUT (and any others) +with bodies, however it does not handle RSO endpoints which require an +`Authorization` header parameter. This handles errors but provides only minimal +failure information. Rate limits are enforced, so requests will wait to complete +when Riven is at the rate limit. Set `RGAPI_KEY` env var then run: ```bash diff --git a/example/proxy/src/main.rs b/example/proxy/src/main.rs index 55e9b05..2805e53 100644 --- a/example/proxy/src/main.rs +++ b/example/proxy/src/main.rs @@ -23,8 +23,7 @@ lazy_static! { std::fs::read_to_string(path).ok() }) .expect("Failed to find RGAPI_KEY env var or apikey.txt."); - RiotApi::with_config(RiotApiConfig::with_key(api_key.trim()) - .preconfig_burst()) + RiotApi::new(RiotApiConfig::with_key(api_key.trim()).preconfig_burst()) }; } diff --git a/riven/src/config.rs b/riven/src/config.rs index 83a0780..6132c8c 100644 --- a/riven/src/config.rs +++ b/riven/src/config.rs @@ -19,11 +19,11 @@ pub struct RiotApiConfig { } impl RiotApiConfig { - /// Request header name for the Riot API key. + /// Request header name for the Riot API key, `"X-Riot-Token"`. /// /// When using `set_client_builder`, the supplied builder should include /// this default header with the Riot API key as the value. - const RIOT_KEY_HEADER: &'static str = "X-Riot-Token"; + pub const RIOT_KEY_HEADER: &'static str = "X-Riot-Token"; /// `"https://{}.api.riotgames.com"` /// @@ -92,7 +92,7 @@ impl RiotApiConfig { /// Creates a new `RiotApiConfig` with the given client builder. /// /// The client builder default headers should include a value for - /// `RiotApiConfig::RIOT_KEY_HEADER`, otherwise authentication will fail. + /// [`RiotApiConfig::RIOT_KEY_HEADER`] (`"X-Riot-Token"`), otherwise authentication will fail. /// /// * `retries = 3` (`RiotApiConfig::DEFAULT_RETRIES`). /// * `burst_factor = 0.99` (`preconfig_burst`). @@ -292,3 +292,9 @@ impl RiotApiConfig { self } } + +impl> From for RiotApiConfig { + fn from(api_key: T) -> Self { + Self::with_key(api_key) + } +} diff --git a/riven/src/lib.rs b/riven/src/lib.rs index a0351e8..0ae3098 100644 --- a/riven/src/lib.rs +++ b/riven/src/lib.rs @@ -25,13 +25,13 @@ //! Data structs and endpoints are automatically generated from the //! [Riot API Reference](https://developer.riotgames.com/api-methods/) ([Swagger](http://www.mingweisamuel.com/riotapi-schema/tool/)). //! -//! ## Design +//! # Design //! //! * Fast, asynchronous, thread-safe. //! * Automatically retries failed requests. //! * Supports all endpoints, kept up-to-date using [riotapi-schema](https://github.com/MingweiSamuel/riotapi-schema). //! -//! ## Usage +//! # Usage //! //! ```rust //! use riven::RiotApi; @@ -42,7 +42,7 @@ //! rt.block_on(async { //! // Create RiotApi instance from key string. //! let api_key = std::env!("RGAPI_KEY"); // "RGAPI-01234567-89ab-cdef-0123-456789abcdef"; -//! let riot_api = RiotApi::with_key(api_key); +//! let riot_api = RiotApi::new(api_key); //! //! // Get summoner data. //! let summoner = riot_api.summoner_v4() @@ -80,9 +80,14 @@ //! 9) Irelia 46465 (5) //! 10) Vladimir 37176 (5) //! ``` -//! ### Feature Flags +//! The [`RiotApi` struct documentation](https://docs.rs/riven/latest/riven/struct.RiotApi.html) +//! contains additional usage information. The [tests](https://github.com/MingweiSamuel/Riven/tree/v/2.x.x/riven/tests) +//! and [example proxy](https://github.com/MingweiSamuel/Riven/tree/v/2.x.x/example/proxy) +//! provide more example usage. //! -//! #### Nightly vs Stable +//! ## Feature Flags +//! +//! ### Nightly vs Stable //! //! Enable the `nightly` feature to use nightly-only functionality. This enables //! [nightly optimizations in the `parking_lot` crate](https://github.com/Amanieu/parking_lot#nightly-vs-stable). @@ -91,7 +96,7 @@ //! riven = { version = "...", features = [ "nightly" ] } //! ``` //! -//! #### rustls +//! ### rustls //! //! Riven uses [reqwest](https://github.com/seanmonstar/reqwest) for making requests. By default, reqwest uses the native TLS library. //! If you prefer using [rustls](https://github.com/ctz/rustls) you can do so by turning off the Riven default features @@ -103,11 +108,11 @@ //! //! Riven is additionally able to produce [tracing](https://docs.rs/tracing) spans for requests if the `tracing` feature is enabled. This feature is disabled by default. //! -//! ### Docs +//! ## Docs //! //! [On docs.rs](https://docs.rs/riven/). //! -//! ### Error Handling +//! ## Error Handling //! //! Riven returns either `Result` or `Result>` within futures. //! @@ -126,12 +131,12 @@ //! attempted, and the Reqwest `Response` object. //! //! You can configure the number of time Riven retries using -//! `RiotApiConfig::set_retries(...)` and the `RiotApi::with_config(config)` +//! `RiotApiConfig::set_retries(...)` and the `RiotApi::from_config(config)` //! constructor. By default, Riven retries up to 3 times (4 requests total). //! Some errors, such as 400 client errors, are not retried as they would //! inevitably fail again. //! -//! ### Semantic Versioning +//! ## Semantic Versioning //! //! This package follows semantic versioning to an extent. However, the Riot API //! itself changes often and does not follow semantic versioning, which makes @@ -147,23 +152,24 @@ //! Parts of Riven that do not depend on Riot API changes do follow semantic //! versioning. //! -//! ### Additional Help +//! ## Additional Help //! //! Feel free to [make an issue](https://github.com/MingweiSamuel/Riven/issues/new) //! if you are have any questions or trouble with Riven. //! -//! ## Development +//! # Development //! //! NodeJS is used to generate code for Riven. The -//! [`srcgen/`](https://github.com/MingweiSamuel/Riven/tree/master/srcgen) +//! [`riven/srcgen`](https://github.com/MingweiSamuel/Riven/tree/v/2.x.x/riven/srcgen) //! folder contains the code and [doT.js](https://olado.github.io/doT/index.html) //! templates. `index.js` lists the JSON files downloaded and used to generate the //! code. //! //! To set up the srcgen, you will first need to install NodeJS. Then enter the -//! srcgen folder and run `npm ci` (or `npm install`) to install dependencies. +//! `riven/srcgen` folder and run `npm ci` (or `npm install`) to install +//! dependencies. //! -//! To run the srcgen use `node srcgen` from the main folder. +//! To run the srcgen use `node riven/srcgen` from the repository root. //! //! diff --git a/riven/src/riot_api.rs b/riven/src/riot_api.rs index a6906e1..fb1aafd 100644 --- a/riven/src/riot_api.rs +++ b/riven/src/riot_api.rs @@ -19,11 +19,16 @@ use crate::util::InsertOnlyCHashMap; /// /// # Usage /// -/// Construct an instance using [`with_key(api_key)`](RiotApi::with_key) or -/// [`with_config(config)`](RiotApi::with_config). +/// Construct an instance using [`RiotApi::new(api_key or config)`](RiotApi::new). +/// The parameter may be a Riot API key string or a [`RiotApiConfig`]. Riot API +/// keys are obtained from the [Riot Developer Portal](https://developer.riotgames.com/) +/// and look like `"RGAPI-01234567-89ab-cdef-0123-456789abcdef"`. /// -/// An instance provides access to "endpoint handles" which in turn provide access -/// to individual API method calls. For example, getting a summoner by name: +/// An instance provides access to "endpoint handles" which in turn provide +/// access to individual API method calls. For example, to get a summoner by +/// name we first access the [`summoner_v4()`](RiotApi::summoner_v4) endpoints +/// then call the [`get_by_summoner_name()`](crate::endpoints::SummonerV4::get_by_summoner_name) +/// method: /// ```ignore /// riot_api.summoner_v4().get_by_summoner_name(Region::NA, "LugnutsK") /// ``` @@ -31,14 +36,14 @@ use crate::util::InsertOnlyCHashMap; /// # Rate Limiting /// /// The Riot Game API enforces _dynamic_ rate limiting, meaning that rate limits are -/// specified in response headers and (theoretically) could change at any time. +/// specified in response headers and can change at any time. /// Riven keeps track of changing rate limits seamlessly, preventing you from /// getting blacklisted. /// -/// Riven's rate limiting is highly efficient, meaning that it can reach the limits -/// of your rate limit without going over. +/// Riven's rate limiting is highly efficient; it can use the full throughput +/// of your rate limit without triggering 429 errors. /// -/// To adjust rate limiting, see [RiotApiConfig](crate::RiotApiConfig) and use +/// To adjust rate limiting, see [RiotApiConfig] and use /// [`with_config(config)`](RiotApi::with_config) to construct an instance. pub struct RiotApi { /// Configuration settings. @@ -51,10 +56,11 @@ pub struct RiotApi { } impl RiotApi { - /// Constructs a new instance from the given [RiotApiConfig](crate::RiotApiConfig), consuming it. - pub fn with_config(mut config: RiotApiConfig) -> Self { + /// Constructs a new instance from an API key (e.g. `"RGAPI-01234567-89ab-cdef-0123-456789abcdef"`) or a [RiotApiConfig]. + pub fn new(config: impl Into) -> Self { + let mut config = config.into(); let client_builder = config.client_builder.take() - .expect("!NONE CLIENT_BUILDER IN CONFIG."); + .expect("CLIENT_BUILDER IN CONFIG SHOULD NOT BE NONE."); Self { config: config, client: client_builder.build().expect("Failed to create client from builder."), @@ -62,13 +68,20 @@ impl RiotApi { } } + /// Constructs a new instance from the given [RiotApiConfig](crate::RiotApiConfig), consuming it. + #[deprecated(since = "2.0", note = "use `RiotApi::new(config)` instead")] + pub fn with_config(config: RiotApiConfig) -> Self { + Self::new(config) + } + /// Constructs a new instance from the given API key, using default configuration. /// /// `api_key` should be a Riot Games API key from /// [https://developer.riotgames.com/](https://developer.riotgames.com/), /// and should look like `"RGAPI-01234567-89ab-cdef-0123-456789abcdef"`. + #[deprecated(since = "2.0", note = "use `RiotApi::new(api_key)` instead")] pub fn with_key(api_key: impl AsRef<[u8]>) -> Self { - Self::with_config(RiotApiConfig::with_key(api_key)) + Self::new(api_key) } /// This method should generally not be used directly. Consider using endpoint wrappers instead. diff --git a/riven/tests/testutils.rs b/riven/tests/testutils.rs index 97a2b02..92e0ad0 100644 --- a/riven/tests/testutils.rs +++ b/riven/tests/testutils.rs @@ -9,8 +9,7 @@ lazy_static! { let api_key = std::env::var("RGAPI_KEY").ok() .or_else(|| std::fs::read_to_string("apikey.txt").ok()) .expect("Failed to find RGAPI_KEY env var or apikey.txt."); - RiotApi::with_config(RiotApiConfig::with_key(api_key.trim()) - .preconfig_burst()) + RiotApi::new(RiotApiConfig::with_key(api_key.trim()).preconfig_burst()) }; }