View Source GitHub.Plugin.RedixRedirectCache (GitHub REST API Client v0.0.8)

Use Redis to cache redirect locations to avoid unexpected rate limits

Warning

This plugin caches information about the names and locations of private repositories, potentially disclosing information if not used carefully.

GitHub's API uses Conditional Requests to provide fast responses when the client already has the latest information. Furthermore, apps with heavy API usage benefit from the fact that 304 responses don't count against rate limits.

However, it may not be obvious to API users that redirect responses always count against your rate limit, even if the ultimate location returns a 304 response.

This module provides two plugins: check_cache/2 and update_cache/2. When run before an API request, check_cache/2 will check the configured Redis server for a known final location for the intended request. If found, it will modify the request to use the new URL instead.

If the API returns a successful or unmodified response, and the final location differs from the original location (meaning a redirect took place), then is will store the new location in in the cache.

limitations

Limitations

  • This plugin requires the client plugin to modify the Operation when a redirection takes place. Otherwise, it will not know that the final location has changed.

  • This plugin cannot know the exact HTTP status code that accompanied the redirect. As a result, there is a risk that it will cache temporary redirects as well as permanent ones.

configuration

Configuration

  • server: Required global name of a Redis server, as found in the name option of Redix.start_link/2. This library is not responsible for starting the Redix app or connecting to the server. This can be a single connection name or a list of connections in a pool. If a list is provided, a random server will be chosen for each interaction.

  • cache_prefix: Prefix to use for all Redis cache keys. Defaults to "oapi_github".

  • expiration: Time, in seconds, before cached data should expire. Defaults to 30 days.

These options may be passed via the plugin definition or by global configuration:

config :oapi_github,
  stack: [
    {GitHub.Plugin.RedixRedirectCache, :check_cache, server: :redix_server_1},
    # ...
  ]

config :oapi_github, GitHub.Plugin.RedixRedirectCache,
  server: :redix_server_1

cache-keys

Cache Keys

Cache keys used by this module have the following parts (separated by colons):

  • A standard prefix (see prefix configuration),
  • The server for the request (ex. api.github.com),
  • The path of the request (ex. /repos/aj-foster),
  • A SHA-256 hash of the auth token used.

By including the hashed auth token in the key, we can be reasonably sure that cached data will not be returned to a user that does not have access to the original data. While this may seem trivial for location data, remember that GitHub deliberately returns 404 responses for private repositories rather than 403 responses.

Link to this section Summary

Functions

Check Redis for cached location changes for the current request

Cache redirect locations

Link to this section Functions

Link to this function

check_cache(operation, options)

View Source
@spec check_cache(
  GitHub.Operation.t(),
  keyword()
) :: {:ok, GitHub.Operation.t()}

Check Redis for cached location changes for the current request

This plugin only affects GET requests. If a cached location is found, the URL of the operation will change to match the known final destination.

configuration

Configuration

This plugin requires the server configuration, and uses the cache_prefix configuration. See Configuration above for more information.

Link to this function

update_cache(operation, options)

View Source
@spec update_cache(
  GitHub.Operation.t(),
  keyword()
) :: {:ok, GitHub.Operation.t()}

Cache redirect locations

This plugin only affects GET requests. In the event of a successful (200) or unmodified (304) response, this will check whether the original URL matches the final URL for the request. If they differ, then it will store the updated location. If they do not differ because the location was updated in check_cache/2, then the expiration of the cached location will be extended.