Skip to content

Commit 914af9c

Browse files
committed
fix: reject non-finite chapterId and out-of-range limit/page (#274)
- reject nan/inf/-inf/Infinity/1e400 chapterId values with a clear 400 instead of letting them reach PyMySQL and raise an unformatted 500 - reject limit/page < 1 with a clear 400 instead of falling through to Flask-SQLAlchemy's bare 404 from paginate(error_out=True) - truncate raw query-param values echoed into error messages to 50 chars - document the new 400 responses for the paginated endpoints and /hadiths in spec.v1.yml
1 parent 26ab099 commit 914af9c

2 files changed

Lines changed: 34 additions & 5 deletions

File tree

main.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import functools
2+
import math
23
from flask import Flask, jsonify, request, abort
34
from sqlalchemy import and_, func, or_
45
from werkzeug.exceptions import HTTPException
@@ -28,6 +29,16 @@ def jsonify_http_error(error):
2829
return jsonify(response), error.code
2930

3031

32+
MAX_PARAM_ECHO_LEN = 50
33+
34+
35+
def _truncate_param(value):
36+
value = str(value)
37+
if len(value) > MAX_PARAM_ECHO_LEN:
38+
return value[:MAX_PARAM_ECHO_LEN] + "..."
39+
return value
40+
41+
3142
def paginate_results(f):
3243
@functools.wraps(f)
3344
def decorated_function(*args, **kwargs):
@@ -37,12 +48,17 @@ def decorated_function(*args, **kwargs):
3748
try:
3849
limit = int(limit_param)
3950
except (TypeError, ValueError):
40-
abort(400, f"Invalid 'limit' query parameter: '{limit_param}' is not an integer.")
51+
abort(400, f"Invalid 'limit' query parameter: '{_truncate_param(limit_param)}' is not an integer.")
4152

4253
try:
4354
page = int(page_param)
4455
except (TypeError, ValueError):
45-
abort(400, f"Invalid 'page' query parameter: '{page_param}' is not an integer.")
56+
abort(400, f"Invalid 'page' query parameter: '{_truncate_param(page_param)}' is not an integer.")
57+
58+
if limit < 1:
59+
abort(400, "Invalid 'limit' query parameter: must be >= 1.")
60+
if page < 1:
61+
abort(400, "Invalid 'page' query parameter: must be >= 1.")
4662

4763
queryset = f(*args, **kwargs).paginate(page=page, per_page=limit, max_per_page=100)
4864
result = {
@@ -140,9 +156,12 @@ def api_hadiths():
140156
chapter_id = request.args.get("chapterId")
141157
if chapter_id:
142158
try:
143-
chapter_id = float(chapter_id)
144-
except ValueError:
145-
abort(400, f"Invalid 'chapterId' query parameter: '{chapter_id}' is not a number.")
159+
parsed_chapter_id = float(chapter_id)
160+
except (TypeError, ValueError):
161+
abort(400, f"Invalid 'chapterId' query parameter: '{_truncate_param(chapter_id)}' is not a number.")
162+
if not math.isfinite(parsed_chapter_id):
163+
abort(400, f"Invalid 'chapterId' query parameter: '{_truncate_param(chapter_id)}' is not a finite number.")
164+
chapter_id = parsed_chapter_id
146165
query = query.filter_by(babID=chapter_id)
147166

148167
hadith_number = request.args.get("hadithNumber")

spec.v1.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ paths:
4747
items:
4848
$ref: "#/components/schemas/Collection"
4949
- $ref: "#/components/schemas/PaginatedResponse"
50+
"400":
51+
description: Bad request (invalid 'limit' or 'page' query parameter)
5052
parameters:
5153
- $ref: "#/components/parameters/limit"
5254
- $ref: "#/components/parameters/page"
@@ -86,6 +88,8 @@ paths:
8688
items:
8789
$ref: "#/components/schemas/Book"
8890
- $ref: "#/components/schemas/PaginatedResponse"
91+
"400":
92+
description: Bad request (invalid 'limit' or 'page' query parameter)
8993
parameters:
9094
- in: path
9195
name: collectionName
@@ -137,6 +141,8 @@ paths:
137141
items:
138142
$ref: "#/components/schemas/Chapter"
139143
- $ref: "#/components/schemas/PaginatedResponse"
144+
"400":
145+
description: Bad request (invalid 'limit' or 'page' query parameter)
140146
parameters:
141147
- in: path
142148
name: collectionName
@@ -201,6 +207,8 @@ paths:
201207
items:
202208
$ref: "#/components/schemas/Hadith"
203209
- $ref: "#/components/schemas/PaginatedResponse"
210+
"400":
211+
description: Bad request (invalid 'limit' or 'page' query parameter)
204212
parameters:
205213
- in: path
206214
name: collectionName
@@ -258,6 +266,8 @@ paths:
258266
items:
259267
$ref: "#/components/schemas/Hadith"
260268
- $ref: "#/components/schemas/PaginatedResponse"
269+
"400":
270+
description: Bad request (invalid 'limit', 'page', or 'chapterId' query parameter)
261271
parameters:
262272
- in: query
263273
name: collection

0 commit comments

Comments
 (0)