Rate limit REST API made with connexion and swagger

Viewed 909

I'm building a REST API using Flask and connexion. (Python)

I'm adding the api to the connexion app using a swagger.yml file that contains the definitions of all the endpoints, methods, etc...

The question is, how can I add a rate limit on a specific resource/route/call ?

I can't seem to find it in the documentation.

Thanks.

2 Answers

Connexion is a flask application so many techniques that work with flask work with connexion.

We successfully used Flask-Limter to do rate limiting.

import os

import connexion

APP = connexion.FlaskApp(
    __name__, specification_dir=os.environ.get("OPENAPI_LOCATION", ".")
)
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address

import service.global_app as global_app

# This is for rate limiting (flask-limiter)
# Ref: https://limits.readthedocs.io/en/stable/storage.html#storage-scheme
APP.app.config["RATELIMIT_STORAGE_URI"] = (
    "redis://" f"{REDIS_HOST}:{REDIS_PORT}/{REDIS_DB + 1}"
)
# Kill switch for rate limiter
APP.app.config["RATELIMIT_ENABLED"] = True
# Policy for what to do if REDIS is down
APP.app.config["RATELIMIT_IN_MEMORY_FALLBACK"] = True
APP.app.config["RATELIMIT_HEADERS_ENABLED"] = True
APP.app.config["RATELIMIT_SWALLOW_ERRORS"] = os.environ.get("ENV", "") != "DEV"


LIMITER = Limiter(
    global_app.APP.app,
    key_func=get_remote_address,
    # 1
    default_limits=[DAILY_LIMIT, HOURLY_LIMIT],
)

@LIMITER.limit("3/second", override_defaults=True, exempt_when=exempt_when)
def simple_search_dsl_async(
) -> str:
    return "Hi"

You could use the X-Rate-Limit-* HTTP headers along with the http 429 status code.

This practically looks like in openapi:

  ....
  responses:
    "200":
      description: Success response
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/YourResponseModel"
      headers:
        "X-Rate-Limit-Limit": {
          "description": "The number of allowed requests in the current period",
          "schema": {
            "type": "integer"
          }
        } ,
        "X-Rate-Limit-Remaining": {
          "description": "The number of remaining requests in the current period",
          "schema": {
            "type": "integer"
          }
        },
        "X-Rate-Limit-Reset": {
         "description": "The number of seconds left in the current period",
         "schema": {
           "type": "integer"
         }
      }
    "429": 
      description: Too many requests
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorMessageResponse"

  ....
Related