From f4aaa31d00be1d81c41ed9272f8394a92495f210 Mon Sep 17 00:00:00 2001 From: James Turk Date: Fri, 10 Jan 2025 17:23:03 -0600 Subject: [PATCH] API keys and httpx --- requirements.txt | 1 + scrapple/hearings.py | 39 ++++++++++++++++++++++++++------------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/requirements.txt b/requirements.txt index 6fb1880..1ed029a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,4 @@ itsdangerous==2.1.2 Jinja2==3.1.2 MarkupSafe==2.1.1 Werkzeug==2.2.2 +httpx==0.28.1 diff --git a/scrapple/hearings.py b/scrapple/hearings.py index b6dfc5e..f274c37 100644 --- a/scrapple/hearings.py +++ b/scrapple/hearings.py @@ -4,8 +4,30 @@ import pathlib from . import app from flask import request, abort -BASE_API_URL = "https://scrapple.fly.io/hearings/house/118/" +BASE_API_URL = "https://scrapple.fly.io/hearings/" BASE_DIR = pathlib.Path("data/congress-hearing-118-house") +# not actually secret, but for testing API Keys +API_SECRET = "53cR3T" + + +def _api_key_check(): + key = request.args.get("api_key", None) + if not key: + abort(401, "Must provide api_key parameter.") + pieces = key.split("-", 1) + if len(pieces) != 2 or pieces[1] != API_SECRET: + abort(401, "API Key should be in format '{username}-{secret}'") + + +def _shortened(hearing): + """return compact hearing form for list view""" + return { + "chamber": hearing["request"]["chamber"], + "congress": hearing["request"]["congress"], + "jacketNumber": hearing["request"]["jacketNumber"], + "updateDate": hearing["hearing"]["updateDate"], + "url": BASE_API_URL + hearing["request"]["jacketNumber"], + } def _load_hearings(): @@ -20,19 +42,9 @@ ALL_HEARINGS = _load_hearings() HEARING_IDS = list(ALL_HEARINGS.keys()) # semi-consistent ordering -def shortened(hearing): - """return compact hearing form for list view""" - return { - "chamber": hearing["request"]["chamber"], - "congress": hearing["request"]["congress"], - "jacketNumber": hearing["request"]["jacketNumber"], - "updateDate": hearing["hearing"]["updateDate"], - "url": BASE_API_URL + hearing["request"]["jacketNumber"], - } - - @app.route("/hearings") def hearings_list(): + _api_key_check() offset = int(request.args.get("offset", 0)) limit = min(int(request.args.get("limit", 50)), 200) format = request.args.get("format", "json") @@ -49,7 +61,7 @@ def hearings_list(): hearing_ids = HEARING_IDS[offset : offset + limit] hearings = [ALL_HEARINGS[h] for h in hearing_ids] return { - "hearings": [shortened(h) for h in hearings], + "hearings": [_shortened(h) for h in hearings], "pagination": {"count": len(ALL_HEARINGS), "next": next_url}, "chamber": { "chamber": "house", @@ -62,6 +74,7 @@ def hearings_list(): @app.route("/hearings/") def hearings_detail(jacket_id): + _api_key_check() if jacket_id not in ALL_HEARINGS: abort(404) return ALL_HEARINGS[jacket_id]