Add RiotApi::new(impl Into<RiotApiConfig>), deprecate old constructors, update docs

- Adds `From<AsRef<[u8]>> for RiotApiConfig` for API keys for the above.
This commit is contained in:
Mingwei Samuel 2021-09-19 11:22:09 -07:00
parent 8f5d7327d1
commit 1a0ae872f5
7 changed files with 88 additions and 52 deletions

View file

@ -15,13 +15,13 @@ Riven's goals are _speed_, _reliability_, and _maintainability_. Riven handles r
Data structs and endpoints are automatically generated from the 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/)). [Riot API Reference](https://developer.riotgames.com/api-methods/) ([Swagger](http://www.mingweisamuel.com/riotapi-schema/tool/)).
## Design # Design
* Fast, asynchronous, thread-safe. * Fast, asynchronous, thread-safe.
* Automatically retries failed requests. * Automatically retries failed requests.
* Supports all endpoints, kept up-to-date using [riotapi-schema](https://github.com/MingweiSamuel/riotapi-schema). * Supports all endpoints, kept up-to-date using [riotapi-schema](https://github.com/MingweiSamuel/riotapi-schema).
## Usage # Usage
```rust ```rust
use riven::RiotApi; use riven::RiotApi;
@ -32,7 +32,7 @@ let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async { rt.block_on(async {
// Create RiotApi instance from key string. // Create RiotApi instance from key string.
let api_key = std::env!("RGAPI_KEY"); // "RGAPI-01234567-89ab-cdef-0123-456789abcdef"; 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. // Get summoner data.
let summoner = riot_api.summoner_v4() let summoner = riot_api.summoner_v4()
@ -70,9 +70,14 @@ Output:
9) Irelia 46465 (5) 9) Irelia 46465 (5)
10) Vladimir 37176 (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 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). [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" ] } 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. 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 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. 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/). [On docs.rs](https://docs.rs/riven/).
### Error Handling ## Error Handling
Riven returns either `Result<T>` or `Result<Option<T>>` within futures. Riven returns either `Result<T>` or `Result<Option<T>>` within futures.
@ -116,12 +121,12 @@ diagnostic information, such as the source Reqwest error, the number of retries
attempted, and the Reqwest `Response` object. attempted, and the Reqwest `Response` object.
You can configure the number of time Riven retries using 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). 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 Some errors, such as 400 client errors, are not retried as they would
inevitably fail again. inevitably fail again.
### Semantic Versioning ## Semantic Versioning
This package follows semantic versioning to an extent. However, the Riot API This package follows semantic versioning to an extent. However, the Riot API
itself changes often and does not follow semantic versioning, which makes 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 Parts of Riven that do not depend on Riot API changes do follow semantic
versioning. versioning.
### Additional Help ## Additional Help
Feel free to [make an issue](https://github.com/MingweiSamuel/Riven/issues/new) Feel free to [make an issue](https://github.com/MingweiSamuel/Riven/issues/new)
if you are have any questions or trouble with Riven. if you are have any questions or trouble with Riven.
## Development # Development
NodeJS is used to generate code for Riven. The 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) 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 templates. `index.js` lists the JSON files downloaded and used to generate the
code. code.
To set up the srcgen, you will first need to install NodeJS. Then enter the 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.

View file

@ -1,8 +1,15 @@
# Riven Example Proxy # Riven Example Proxy
This is a simple example implementation of a Riot API proxy server using `hyper`. This adds the API key and forwards This is a simple example implementation of a Riot API proxy server using
requests to the Riot API, then returns and forwards responses back to the requester. It handles error cases but only [`hyper`](https://github.com/hyperium/hyper). This adds the API key and
provides minimal failure information. HTTP requests will wait to complete when Riven is waiting on rate limits. 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: Set `RGAPI_KEY` env var then run:
```bash ```bash

View file

@ -23,8 +23,7 @@ lazy_static! {
std::fs::read_to_string(path).ok() std::fs::read_to_string(path).ok()
}) })
.expect("Failed to find RGAPI_KEY env var or apikey.txt."); .expect("Failed to find RGAPI_KEY env var or apikey.txt.");
RiotApi::with_config(RiotApiConfig::with_key(api_key.trim()) RiotApi::new(RiotApiConfig::with_key(api_key.trim()).preconfig_burst())
.preconfig_burst())
}; };
} }

View file

@ -19,11 +19,11 @@ pub struct RiotApiConfig {
} }
impl 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 /// When using `set_client_builder`, the supplied builder should include
/// this default header with the Riot API key as the value. /// 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"` /// `"https://{}.api.riotgames.com"`
/// ///
@ -92,7 +92,7 @@ impl RiotApiConfig {
/// Creates a new `RiotApiConfig` with the given client builder. /// Creates a new `RiotApiConfig` with the given client builder.
/// ///
/// The client builder default headers should include a value for /// 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`). /// * `retries = 3` (`RiotApiConfig::DEFAULT_RETRIES`).
/// * `burst_factor = 0.99` (`preconfig_burst`). /// * `burst_factor = 0.99` (`preconfig_burst`).
@ -292,3 +292,9 @@ impl RiotApiConfig {
self self
} }
} }
impl<T: AsRef<[u8]>> From<T> for RiotApiConfig {
fn from(api_key: T) -> Self {
Self::with_key(api_key)
}
}

View file

@ -25,13 +25,13 @@
//! Data structs and endpoints are automatically generated from the //! 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/)). //! [Riot API Reference](https://developer.riotgames.com/api-methods/) ([Swagger](http://www.mingweisamuel.com/riotapi-schema/tool/)).
//! //!
//! ## Design //! # Design
//! //!
//! * Fast, asynchronous, thread-safe. //! * Fast, asynchronous, thread-safe.
//! * Automatically retries failed requests. //! * Automatically retries failed requests.
//! * Supports all endpoints, kept up-to-date using [riotapi-schema](https://github.com/MingweiSamuel/riotapi-schema). //! * Supports all endpoints, kept up-to-date using [riotapi-schema](https://github.com/MingweiSamuel/riotapi-schema).
//! //!
//! ## Usage //! # Usage
//! //!
//! ```rust //! ```rust
//! use riven::RiotApi; //! use riven::RiotApi;
@ -42,7 +42,7 @@
//! rt.block_on(async { //! rt.block_on(async {
//! // Create RiotApi instance from key string. //! // Create RiotApi instance from key string.
//! let api_key = std::env!("RGAPI_KEY"); // "RGAPI-01234567-89ab-cdef-0123-456789abcdef"; //! 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. //! // Get summoner data.
//! let summoner = riot_api.summoner_v4() //! let summoner = riot_api.summoner_v4()
@ -80,9 +80,14 @@
//! 9) Irelia 46465 (5) //! 9) Irelia 46465 (5)
//! 10) Vladimir 37176 (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 //! 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). //! [nightly optimizations in the `parking_lot` crate](https://github.com/Amanieu/parking_lot#nightly-vs-stable).
@ -91,7 +96,7 @@
//! riven = { version = "...", features = [ "nightly" ] } //! 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. //! 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 //! 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. //! 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/). //! [On docs.rs](https://docs.rs/riven/).
//! //!
//! ### Error Handling //! ## Error Handling
//! //!
//! Riven returns either `Result<T>` or `Result<Option<T>>` within futures. //! Riven returns either `Result<T>` or `Result<Option<T>>` within futures.
//! //!
@ -126,12 +131,12 @@
//! attempted, and the Reqwest `Response` object. //! attempted, and the Reqwest `Response` object.
//! //!
//! You can configure the number of time Riven retries using //! 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). //! 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 //! Some errors, such as 400 client errors, are not retried as they would
//! inevitably fail again. //! inevitably fail again.
//! //!
//! ### Semantic Versioning //! ## Semantic Versioning
//! //!
//! This package follows semantic versioning to an extent. However, the Riot API //! This package follows semantic versioning to an extent. However, the Riot API
//! itself changes often and does not follow semantic versioning, which makes //! 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 //! Parts of Riven that do not depend on Riot API changes do follow semantic
//! versioning. //! versioning.
//! //!
//! ### Additional Help //! ## Additional Help
//! //!
//! Feel free to [make an issue](https://github.com/MingweiSamuel/Riven/issues/new) //! Feel free to [make an issue](https://github.com/MingweiSamuel/Riven/issues/new)
//! if you are have any questions or trouble with Riven. //! if you are have any questions or trouble with Riven.
//! //!
//! ## Development //! # Development
//! //!
//! NodeJS is used to generate code for Riven. The //! 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) //! 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 //! templates. `index.js` lists the JSON files downloaded and used to generate the
//! code. //! code.
//! //!
//! To set up the srcgen, you will first need to install NodeJS. Then enter the //! 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.
//! //!
//! //!

View file

@ -19,11 +19,16 @@ use crate::util::InsertOnlyCHashMap;
/// ///
/// # Usage /// # Usage
/// ///
/// Construct an instance using [`with_key(api_key)`](RiotApi::with_key) or /// Construct an instance using [`RiotApi::new(api_key or config)`](RiotApi::new).
/// [`with_config(config)`](RiotApi::with_config). /// 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 /// An instance provides access to "endpoint handles" which in turn provide
/// to individual API method calls. For example, getting a summoner by name: /// 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 /// ```ignore
/// riot_api.summoner_v4().get_by_summoner_name(Region::NA, "LugnutsK") /// riot_api.summoner_v4().get_by_summoner_name(Region::NA, "LugnutsK")
/// ``` /// ```
@ -31,14 +36,14 @@ use crate::util::InsertOnlyCHashMap;
/// # Rate Limiting /// # Rate Limiting
/// ///
/// The Riot Game API enforces _dynamic_ rate limiting, meaning that rate limits are /// 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 /// Riven keeps track of changing rate limits seamlessly, preventing you from
/// getting blacklisted. /// getting blacklisted.
/// ///
/// Riven's rate limiting is highly efficient, meaning that it can reach the limits /// Riven's rate limiting is highly efficient; it can use the full throughput
/// of your rate limit without going over. /// 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. /// [`with_config(config)`](RiotApi::with_config) to construct an instance.
pub struct RiotApi { pub struct RiotApi {
/// Configuration settings. /// Configuration settings.
@ -51,10 +56,11 @@ pub struct RiotApi {
} }
impl RiotApi { impl RiotApi {
/// Constructs a new instance from the given [RiotApiConfig](crate::RiotApiConfig), consuming it. /// Constructs a new instance from an API key (e.g. `"RGAPI-01234567-89ab-cdef-0123-456789abcdef"`) or a [RiotApiConfig].
pub fn with_config(mut config: RiotApiConfig) -> Self { pub fn new(config: impl Into<RiotApiConfig>) -> Self {
let mut config = config.into();
let client_builder = config.client_builder.take() let client_builder = config.client_builder.take()
.expect("!NONE CLIENT_BUILDER IN CONFIG."); .expect("CLIENT_BUILDER IN CONFIG SHOULD NOT BE NONE.");
Self { Self {
config: config, config: config,
client: client_builder.build().expect("Failed to create client from builder."), 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. /// Constructs a new instance from the given API key, using default configuration.
/// ///
/// `api_key` should be a Riot Games API key from /// `api_key` should be a Riot Games API key from
/// [https://developer.riotgames.com/](https://developer.riotgames.com/), /// [https://developer.riotgames.com/](https://developer.riotgames.com/),
/// and should look like `"RGAPI-01234567-89ab-cdef-0123-456789abcdef"`. /// 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 { 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. /// This method should generally not be used directly. Consider using endpoint wrappers instead.

View file

@ -9,8 +9,7 @@ lazy_static! {
let api_key = std::env::var("RGAPI_KEY").ok() let api_key = std::env::var("RGAPI_KEY").ok()
.or_else(|| std::fs::read_to_string("apikey.txt").ok()) .or_else(|| std::fs::read_to_string("apikey.txt").ok())
.expect("Failed to find RGAPI_KEY env var or apikey.txt."); .expect("Failed to find RGAPI_KEY env var or apikey.txt.");
RiotApi::with_config(RiotApiConfig::with_key(api_key.trim()) RiotApi::new(RiotApiConfig::with_key(api_key.trim()).preconfig_burst())
.preconfig_burst())
}; };
} }