Skip to content

Commit df37dfb

Browse files
authored
feat: Added hard limits to API endpoints (#1078)
1 parent 5c5b2ad commit df37dfb

File tree

4 files changed

+97
-13
lines changed

4 files changed

+97
-13
lines changed

api/tests/integration/test_feeds_api.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,3 +815,26 @@ def test_gtfs_redirect(client):
815815
assert feed["redirects"][0]["comment"] == ""
816816
# spreadsheet contains '10'
817817
assert feed["redirects"][0]["target_id"] == "mdb-10"
818+
819+
820+
@pytest.mark.parametrize(
821+
"values",
822+
[
823+
{"endpoint": "/v1/feeds", "hard_limit": 3500},
824+
{"endpoint": "/v1/gtfs_feeds", "hard_limit": 2500},
825+
{"endpoint": "/v1/gtfs_rt_feeds", "hard_limit": 1000},
826+
{"endpoint": "/v1/gtfs_feeds/mdb-1/datasets", "hard_limit": 500},
827+
{"endpoint": "/v1/search", "hard_limit": 3500},
828+
],
829+
)
830+
def test_hard_limits(client, monkeypatch, values):
831+
"""Test that an error is returned if we request more than the hard limit for each endpoint"""
832+
hard_limit = values["hard_limit"]
833+
834+
response = client.request(
835+
"GET",
836+
values["endpoint"],
837+
headers=authHeaders,
838+
params={"limit": hard_limit + 1},
839+
)
840+
assert response.status_code != 200

api/tests/unittest/test_feeds.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,16 @@ def test_feeds_get(client: TestClient, mocker):
8787
"""
8888
Unit test for get_feeds
8989
"""
90+
# Build the chain of calls to mimic what is done in impl.feeds_api_impl.FeedsApiImpl.get_feeds
9091
mock_filter = mocker.patch.object(FeedFilter, "filter")
92+
mock_filter_limit = Mock()
9193
mock_filter_offset = Mock()
9294
mock_filter_order_by = Mock()
9395
mock_options = Mock()
9496
mock_filter.return_value.filter.return_value.filter.return_value.order_by.return_value = mock_filter_order_by
9597
mock_filter_order_by.options.return_value = mock_options
96-
mock_options.offset.return_value = mock_filter_offset
98+
mock_options.limit.return_value = mock_filter_limit
99+
mock_filter_limit.offset.return_value = mock_filter_offset
97100
# Target is set to None as deep copy is failing for unknown reasons
98101
# At the end of the test, the target is set back to the original value
99102
mock_feed.redirectingids[0].target = None

docs/DatabaseCatalogAPI.yaml

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ paths:
4242
- "feeds"
4343
operationId: getFeeds
4444
parameters:
45-
- $ref: "#/components/parameters/limit_query_param"
45+
- $ref: "#/components/parameters/limit_query_param_feeds_endpoint"
4646
- $ref: "#/components/parameters/offset"
4747
- $ref: "#/components/parameters/status"
4848
- $ref: "#/components/parameters/provider"
@@ -88,7 +88,7 @@ paths:
8888
- "feeds"
8989
operationId: getGtfsFeeds
9090
parameters:
91-
- $ref: "#/components/parameters/limit_query_param"
91+
- $ref: "#/components/parameters/limit_query_param_gtfs_feeds_endpoint"
9292
- $ref: "#/components/parameters/offset"
9393
- $ref: "#/components/parameters/provider"
9494
- $ref: "#/components/parameters/producer_url"
@@ -117,7 +117,7 @@ paths:
117117
- "feeds"
118118
operationId: getGtfsRtFeeds
119119
parameters:
120-
- $ref: "#/components/parameters/limit_query_param"
120+
- $ref: "#/components/parameters/limit_query_param_gtfs_rt_feeds_endpoint"
121121
- $ref: "#/components/parameters/offset"
122122
- $ref: "#/components/parameters/provider"
123123
- $ref: "#/components/parameters/producer_url"
@@ -184,7 +184,7 @@ paths:
184184
operationId: getGtfsFeedDatasets
185185
parameters:
186186
- $ref: "#/components/parameters/latest_query_param"
187-
- $ref: "#/components/parameters/limit_query_param"
187+
- $ref: "#/components/parameters/limit_query_param_datasets_endpoint"
188188
- $ref: "#/components/parameters/offset"
189189
- $ref: "#/components/parameters/downloaded_after"
190190
- $ref: "#/components/parameters/downloaded_before"
@@ -277,7 +277,7 @@ paths:
277277
tags:
278278
- "search"
279279
parameters:
280-
- $ref: "#/components/parameters/limit_query_param"
280+
- $ref: "#/components/parameters/limit_query_param_search_endpoint"
281281
- $ref: "#/components/parameters/offset"
282282
- $ref: "#/components/parameters/statuses"
283283
- $ref: "#/components/parameters/feed_id_query_param"
@@ -1060,14 +1060,64 @@ components:
10601060
type: boolean
10611061
default: null
10621062

1063-
limit_query_param:
1063+
limit_query_param_feeds_endpoint:
10641064
name: limit
10651065
in: query
10661066
description: The number of items to be returned.
10671067
required: False
10681068
schema:
10691069
type: integer
10701070
minimum: 0
1071+
maximum: 3500
1072+
default: 3500
1073+
example: 10
1074+
1075+
limit_query_param_gtfs_feeds_endpoint:
1076+
name: limit
1077+
in: query
1078+
description: The number of items to be returned.
1079+
required: False
1080+
schema:
1081+
type: integer
1082+
minimum: 0
1083+
maximum: 2500
1084+
default: 2500
1085+
example: 10
1086+
1087+
limit_query_param_gtfs_rt_feeds_endpoint:
1088+
name: limit
1089+
in: query
1090+
description: The number of items to be returned.
1091+
required: False
1092+
schema:
1093+
type: integer
1094+
minimum: 0
1095+
maximum: 1000
1096+
default: 1000
1097+
example: 10
1098+
1099+
limit_query_param_datasets_endpoint:
1100+
name: limit
1101+
in: query
1102+
description: The number of items to be returned.
1103+
required: False
1104+
schema:
1105+
type: integer
1106+
minimum: 0
1107+
maximum: 500
1108+
default: 500
1109+
example: 10
1110+
1111+
limit_query_param_search_endpoint:
1112+
name: limit
1113+
in: query
1114+
description: The number of items to be returned.
1115+
required: False
1116+
schema:
1117+
type: integer
1118+
minimum: 0
1119+
maximum: 3500
1120+
default: 3500
10711121
example: 10
10721122

10731123
offset:

web-app/src/app/services/feeds/types.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,15 @@ export interface components {
555555
/** @description If true, only return official feeds. */
556556
is_official_query_param?: boolean;
557557
/** @description The number of items to be returned. */
558-
limit_query_param?: number;
558+
limit_query_param_feeds_endpoint?: number;
559+
/** @description The number of items to be returned. */
560+
limit_query_param_gtfs_feeds_endpoint?: number;
561+
/** @description The number of items to be returned. */
562+
limit_query_param_gtfs_rt_feeds_endpoint?: number;
563+
/** @description The number of items to be returned. */
564+
limit_query_param_datasets_endpoint?: number;
565+
/** @description The number of items to be returned. */
566+
limit_query_param_search_endpoint?: number;
559567
/** @description Offset of the first item to return. */
560568
offset?: number;
561569
/** @description General search query to match against transit provider, location, and feed name. */
@@ -599,7 +607,7 @@ export interface operations {
599607
getFeeds: {
600608
parameters: {
601609
query?: {
602-
limit?: components['parameters']['limit_query_param'];
610+
limit?: components['parameters']['limit_query_param_feeds_endpoint'];
603611
offset?: components['parameters']['offset'];
604612
status?: components['parameters']['status'];
605613
provider?: components['parameters']['provider'];
@@ -636,7 +644,7 @@ export interface operations {
636644
getGtfsFeeds: {
637645
parameters: {
638646
query?: {
639-
limit?: components['parameters']['limit_query_param'];
647+
limit?: components['parameters']['limit_query_param_gtfs_feeds_endpoint'];
640648
offset?: components['parameters']['offset'];
641649
provider?: components['parameters']['provider'];
642650
producer_url?: components['parameters']['producer_url'];
@@ -662,7 +670,7 @@ export interface operations {
662670
getGtfsRtFeeds: {
663671
parameters: {
664672
query?: {
665-
limit?: components['parameters']['limit_query_param'];
673+
limit?: components['parameters']['limit_query_param_gtfs_rt_feeds_endpoint'];
666674
offset?: components['parameters']['offset'];
667675
provider?: components['parameters']['provider'];
668676
producer_url?: components['parameters']['producer_url'];
@@ -719,7 +727,7 @@ export interface operations {
719727
parameters: {
720728
query?: {
721729
latest?: components['parameters']['latest_query_param'];
722-
limit?: components['parameters']['limit_query_param'];
730+
limit?: components['parameters']['limit_query_param_datasets_endpoint'];
723731
offset?: components['parameters']['offset'];
724732
downloaded_after?: components['parameters']['downloaded_after'];
725733
downloaded_before?: components['parameters']['downloaded_before'];
@@ -803,7 +811,7 @@ export interface operations {
803811
searchFeeds: {
804812
parameters: {
805813
query?: {
806-
limit?: components['parameters']['limit_query_param'];
814+
limit?: components['parameters']['limit_query_param_search_endpoint'];
807815
offset?: components['parameters']['offset'];
808816
status?: components['parameters']['statuses'];
809817
feed_id?: components['parameters']['feed_id_query_param'];

0 commit comments

Comments
 (0)