@fightmegg/riot-rate-limiter

Rate Limiter for Riot Games API

Usage no npm install needed!

<script type="module">
  import fightmeggRiotRateLimiter from 'https://cdn.skypack.dev/@fightmegg/riot-rate-limiter';
</script>

README

Riot Rate Limiter

Version Downloads CircleCI

Node.JS Rate Limiter for Riot Games API

Wiki

Features

Contents

Installation

$ npm install @fightmegg/riot-rate-limiter

Usage

import { RiotRateLimiter } from "@fightmegg/riot-rate-limiter";

const limiter = new RiotRateLimiter();

// async await
const response = await limiter.execute({
  url: "https://euw1.api.riotgames.com/lol/some/method",
  options: {
    headers: {
      "X-Riot-Token": "...",
    },
  },
});

// Promises
limiter
  .execute({
    url: "https://euw1.api.riotgames.com/lol/some/method",
    options: {
      headers: {
        "X-Riot-Token": "...",
      },
    },
  })
  .then((response) => {
    // ...
  });

API

constructor

new RiotRateLimiter({
  debug: boolean = false,
  concurrency: number = 1,
  retryAfterDefault: number = 5000,
  retryCount: number = 4,
  datastore: 'local' | 'ioredis' = 'local'
  redis?: RedisConnectionOptions | RedisConnectionString = null
});

.execute

This library uses node-fetch underneath the hood for making requests. The .execute method literally passes everything given to node-fetch, therefore you can change things like method, headers etc..

Any responses that are not 2xx or 429 will be thrown, and must be caught.

We will auto-retry 429 responses, up until the retryCount limit is hit (defaults to 4), utilising the Retry-After header to respect the API.

limiter.execute({
  url: RequestInfo,
  options: RequestInit,
},
  jobOptions?: Bottleneck.JobOptions
);

The second argument is optional, which allows you to specify JobOptions such as job priority and unique ID for log identification. The weight of a job cannot be changed from the value of 1 no matter what you pass in.

.rateLimiters

This is a map of all of the rate-limiters created, we create at least 1 rate-limiter for the region of the request, and then at least 1 rate-limiter per method underneath that region.

We use the library Bottleneck as our rate-limiter, which supports chaining rate-limiters, meaning that the parents rate-limiter is always respected by its children.

You can access the region rate-limiters via: limiter.rateLimiters[region].main and you can access the method rate-limiters via: limiter.rateLimiters[region][method].main

Helpers

We also provided some helper functions & objects.

extractRegion

This can extract the region or platformId from your URL:

import { extractRegion } from "@fightmegg/riot-rate-limiter";

extractRegion("https://na1.api.riotgames.com/method"); // returns na1

extractMethod

This can extract the method from your URL:

import { extractMethod } from "@fightmegg/riot-rate-limiter";

extractMethod(
  "https://na1.api.riotgames.com/lol/champion-mastery/v4/scores/by-summoner/12345"
); // returns 'CHAMPION_MASTERY.GET_CHAMPION_MASTERY_SCORE'

METHODS & HOST

For those looking to build a RiotGamesAPI library ontop of this rate limiter, we export two object called METHODS & HOST. You can use these exports to create the URLs for you, as seen below:

import { compile } from "path-to-regexp";
import { HOST, METHODS } from "@fightmegg/riot-rate-limiter";

const createHost = compile(HOST, { encode: encodeURIComponent });
const createPath = compile(METHODS.ACCOUNT.GET_BY_PUUID, {
  encode: encodeURIComponent,
});

const url = `https://${createHost({ platformId: "euw1" })}${createPath({
  puuid: "12345",
})}`;

Debugging

If you want to see want the rate-limiter is currently doing, we use the debug module for logging. Simply run your app with:

DEBUG=riotratelimiter* node ...

Testing

Unit tests: npm test

E2E tests: npm run test:e2e

Maintainers

@olliejennings