Skip to content

Commit

Permalink
Merge pull request #37 from canonical/wd-12317
Browse files Browse the repository at this point in the history
feat: Implement Flask-Limiter on the search module
  • Loading branch information
petesfrench authored Jul 26, 2024
2 parents 41670f7 + c622fde commit 4850a23
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 29 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ jobs:

- name: Test Python
run: |
python3 setup.py install --user test
pip install -e .
pip install httpretty
python -m unittest discover tests
check-inclusive-naming:
Expand Down
1 change: 1 addition & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ v1.2.5, 2022-07-12 -- Block some more bot useragents
v1.2.6, 2022-07-13 -- Block one more useragent - "gh"
v1.2.7, 2022-07-15 -- Block more user agents - "Petalbot"
v1.3.0, 2023-02-20 -- Add rate limits
v1.4.0, 2-24-06-21 -- Migrate to Flask.Limiter for rate limits
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ app.add_url_rule(
"/docs/search",
"docs-search",
build_search_view(
app=app
session=session,
site="maas.io/docs",
template_path="docs/search.html",
search_engine_id="xxxxxxxxxx", # Optional argument, required by some of our sites
request_limit="500/day", # Allows your to configure the limit at which the user will be forbidden to query more. Defaults to 500 per day
request_limit="500/day", # Allows your to configure the limit at which the user will be forbidden to query more. Defaults to 2000 per day
)
)
```
Expand Down
46 changes: 22 additions & 24 deletions canonicalwebteam/search/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,28 @@

# Packages
import flask
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address

# Local
from canonicalwebteam.search.models import get_search_results
from limits import storage, strategies, parse

memory_storage = storage.MemoryStorage()
fixed_window = strategies.MovingWindowRateLimiter(memory_storage)


class NoAPIKeyError(Exception):
pass


limiter = Limiter(get_remote_address)


def build_search_view(
app,
session,
site=None,
template_path="search.html",
search_engine_id="009048213575199080868:i3zoqdwqk8o",
site_restricted_search=False,
request_limit="500/day",
request_limit="2000/day",
):
"""
Build and return a view function that will query the
Expand All @@ -33,31 +35,26 @@ def build_search_view(
from canonicalwebteam.search import build_search_view
app = Flask()
app = Flask(__name__)
session = talisker.requests.get_session()
app.add_url_rule(
"/search",
"search",
build_search_view(
app,
session=session,
site="snapcraft.io",
template_path="search.html"
)
)
"""

limiter.init_app(app)

def search_view():
"""
Get search results from Google Custom Search
"""
# Rate limit requests to protect from spamming
# To adjust this rate visit
# https://limits.readthedocs.io/en/latest/quickstart.html#examples
limit = parse(request_limit)
rate_limit = fixed_window.hit(limit)
if not rate_limit:
return flask.abort(429, f"The rate limit is: {request_limit}")

# API key should always be provided as an environment variable
search_api_key = os.getenv("SEARCH_API_KEY")

Expand All @@ -72,16 +69,17 @@ def search_view():
results = None

if query:
results = get_search_results(
session=session,
api_key=search_api_key,
search_engine_id=search_engine_id,
siteSearch=site_search,
site_restricted_search=site_restricted_search,
query=query,
start=start,
num=num,
)
with limiter.limit(request_limit):
results = get_search_results(
session=session,
api_key=search_api_key,
search_engine_id=search_engine_id,
siteSearch=site_search,
site_restricted_search=site_restricted_search,
query=query,
start=start,
num=num,
)

return (
flask.render_template(
Expand Down
8 changes: 6 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

setup(
name="canonicalwebteam.search",
version="1.3.0",
version="1.4.0",
author="Canonical webteam",
author_email="webteam@canonical.com",
url="https://github.com/canonical/canonicalwebteam.search",
Expand All @@ -15,6 +15,10 @@
packages=find_packages(),
long_description=open("README.md").read(),
long_description_content_type="text/markdown",
install_requires=["Flask>=1.0.2", "user-agents>=2.0.0", "limits>=3.2.0"],
install_requires=[
"canonicalwebteam.flask-base>=2.0.0",
"user-agents>=2.0.0",
"Flask-Limiter>=3.8.0",
],
tests_require=["httpretty"],
)
5 changes: 4 additions & 1 deletion tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,15 @@ def setUp(self):

# Default use-case
self.app.add_url_rule(
"/search", "search", build_search_view(session=session)
"/search", "search", build_search_view(self.app, session=session)
)

# Custom use-case
self.app.add_url_rule(
"/docs/search",
"docs-search",
build_search_view(
self.app,
session=session,
site="maas.io/docs",
template_path="docs/search.html",
Expand All @@ -67,6 +68,7 @@ def setUp(self):
"/server/docs/search",
"server-docs-search",
build_search_view(
self.app,
session=session,
template_path="docs/search.html",
site_restricted_search=True,
Expand All @@ -78,6 +80,7 @@ def setUp(self):
"/server/docs/limited/search",
"server-docs-search-limited",
build_search_view(
self.app,
session=session,
template_path="docs/search.html",
site_restricted_search=True,
Expand Down

0 comments on commit 4850a23

Please sign in to comment.