From df3c5ba2d560e789d6caf4e6711a1b15b577c356 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Sun, 19 Mar 2017 22:12:20 -0400 Subject: [PATCH] rate-limiting --- Pipfile | 3 +++ Pipfile.lock | 17 ++++++++++++++++- httpbin/core.py | 15 +++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/Pipfile b/Pipfile index 8cef6dd..6646e73 100644 --- a/Pipfile +++ b/Pipfile @@ -7,7 +7,10 @@ gunicorn = "*" decorator = "*" brotlipy = "*" gevent = "*" +redis = "*" +hiredis = "*" Flask = "*" +Flask-Limiter = "*" [packages.raven] extras = [ "flask",] diff --git a/Pipfile.lock b/Pipfile.lock index 9d7db15..ed06d34 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "972fd2dc19c6b6f8a5b832bf8f656be3971b6e096d09af9926d049c046629ef6" + "sha256": "1f9f2e0fc8779b7c234101d7b6ee0e8802a12b81e07f9d356ae9b7fb710af2bc" }, "requires": {}, "sources": [ @@ -15,6 +15,9 @@ "Flask": { "version": "==0.12" }, + "Flask-Limiter": { + "version": "==0.9.3" + }, "Jinja2": { "version": "==2.9.5" }, @@ -54,14 +57,26 @@ "gunicorn": { "version": "==19.7.0" }, + "hiredis": { + "version": "==0.2.0" + }, "itsdangerous": { "version": "==0.24" }, + "limits": { + "version": "==1.2.1" + }, "pycparser": { "version": "==2.17" }, "raven": { "version": "==6.0.0" + }, + "redis": { + "version": "==2.10.5" + }, + "six": { + "version": "==1.10.0" } }, "develop": {} diff --git a/httpbin/core.py b/httpbin/core.py index ad7b5d5..3e907b5 100644 --- a/httpbin/core.py +++ b/httpbin/core.py @@ -16,6 +16,8 @@ import uuid import argparse from flask import Flask, Response, request, render_template, redirect, jsonify as flask_jsonify, make_response, url_for +from flask_limiter import Limiter +from flask_limiter.util import get_remote_address from six.moves import range as xrange from werkzeug.datastructures import WWWAuthenticate, MultiDict from werkzeug.http import http_date @@ -57,6 +59,19 @@ app.debug = bool(os.environ.get('DEBUG')) if 'SENTRY_DSN' in os.environ: sentry = Sentry(app, dsn=os.environ['SENTRY_DSN']) +# Setup rate-limiting. +if 'REDIS_URL' in os.environ: + app.config['RATELIMIT_STORAGE_URL'] = os.environ['REDIS_URL'] + app.config['RATELIMIT_HEADERS_ENABLED'] = True + + limiter = Limiter( + app, + key_func=get_remote_address, + global_limits=["100000 per day", "10000 per hour"] + ) + + + # Set up Bugsnag exception tracking, if desired. To use Bugsnag, install the # Bugsnag Python client with the command "pip install bugsnag", and set the