Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 1cd836a

Browse files
committedDec 20, 2024·
added option
1 parent 64b0b17 commit 1cd836a

File tree

3 files changed

+15
-13
lines changed

3 files changed

+15
-13
lines changed
 

‎fastapi_jsonapi/api.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ def __init__(
7979
pagination_default_limit: Optional[int] = None,
8080
methods: Iterable[str] = (),
8181
max_cache_size: int = 0,
82+
ending_slash: bool = True,
8283
) -> None:
8384
"""
8485
Initialize router items.
@@ -118,6 +119,7 @@ def __init__(
118119
self.schema_detail = schema
119120
# tuple and not set, so ordering is persisted
120121
self.methods = tuple(methods) or self.DEFAULT_METHODS
122+
self.ending_suffix = "/" if ending_slash else ""
121123

122124
if self.type_ in self.all_jsonapi_routers:
123125
msg = f"Resource type {self.type_!r} already registered"
@@ -187,7 +189,7 @@ def _register_get_resource_list(self, path: str):
187189
status.HTTP_200_OK: {"model": self.list_response_schema},
188190
}
189191
self._router.add_api_route(
190-
path=path,
192+
path=path + self.ending_suffix,
191193
tags=self._tags,
192194
responses=list_response_example | self.default_error_responses,
193195
methods=["GET"],
@@ -201,7 +203,7 @@ def _register_post_resource_list(self, path: str):
201203
status.HTTP_201_CREATED: {"model": self.detail_response_schema},
202204
}
203205
self._router.add_api_route(
204-
path=path,
206+
path=path + self.ending_suffix,
205207
tags=self._tags,
206208
responses=create_resource_response_example | self.default_error_responses,
207209
methods=["POST"],
@@ -216,7 +218,7 @@ def _register_delete_resource_list(self, path: str):
216218
status.HTTP_200_OK: {"model": self.detail_response_schema},
217219
}
218220
self._router.add_api_route(
219-
path=path,
221+
path=path + self.ending_suffix,
220222
tags=self._tags,
221223
responses=detail_response_example | self.default_error_responses,
222224
methods=["DELETE"],
@@ -232,7 +234,7 @@ def _register_get_resource_detail(self, path: str):
232234
self._router.add_api_route(
233235
# TODO: variable path param name (set default name on DetailView class)
234236
# TODO: trailing slash (optional)
235-
path=path + "/{obj_id}",
237+
path=path + "/{obj_id}" + self.ending_suffix,
236238
tags=self._tags,
237239
responses=detail_response_example | self.default_error_responses,
238240
methods=["GET"],
@@ -248,7 +250,7 @@ def _register_patch_resource_detail(self, path: str):
248250
self._router.add_api_route(
249251
# TODO: variable path param name (set default name on DetailView class)
250252
# TODO: trailing slash (optional)
251-
path=path + "/{obj_id}",
253+
path=path + "/{obj_id}" + self.ending_suffix,
252254
tags=self._tags,
253255
responses=update_response_example | self.default_error_responses,
254256
methods=["PATCH"],
@@ -267,7 +269,7 @@ def _register_delete_resource_detail(self, path: str):
267269
self._router.add_api_route(
268270
# TODO: variable path param name (set default name on DetailView class)
269271
# TODO: trailing slash (optional)
270-
path=path + "/{obj_id}",
272+
path=path + "/{obj_id}" + self.ending_suffix,
271273
tags=self._tags,
272274
responses=delete_response_example | self.default_error_responses,
273275
methods=["DELETE"],

‎tests/test_api/test_api_sqla_with_includes.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1525,15 +1525,15 @@ async def test_create_user_and_fetch_data(self, app: FastAPI, client: AsyncClien
15251525
},
15261526
}
15271527
app.url_path_for("get_user_list")
1528-
res = await client.post("/users", json=create_user_body)
1528+
res = await client.post("/users/", json=create_user_body)
15291529
assert res.status_code == status.HTTP_201_CREATED, res.text
15301530
response_data = res.json()
15311531
assert "data" in response_data, response_data
15321532
assert response_data["data"]["attributes"] == create_user_body["data"]["attributes"]
15331533

15341534
user_id = response_data["data"]["id"]
15351535

1536-
res = await client.get(f"/users/{user_id}")
1536+
res = await client.get(f"/users/{user_id}/")
15371537
assert res.status_code == status.HTTP_200_OK, res.text
15381538
response_data = res.json()
15391539
assert "data" in response_data, response_data
@@ -2746,7 +2746,7 @@ async def test_filters_really_works(
27462746
params = {"filter[name]": fake_name}
27472747
assert user_1.name != fake_name
27482748
assert user_2.name != fake_name
2749-
res = await client.get("/users", params=params)
2749+
res = await client.get("/users/", params=params)
27502750
assert res.status_code == status.HTTP_200_OK, res.text
27512751
assert res.json() == {
27522752
"data": [],

‎tests/test_api/test_routers.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ class DependencyInjectionDetailView(DetailViewBaseGeneric):
9696

9797
app = build_app(DependencyInjectionDetailView, resource_type="test_dependency_handler_call")
9898
async with AsyncClient(app=app, base_url="http://test") as client:
99-
res = await client.get("/users/1")
99+
res = await client.get("/users/1/")
100100

101101
assert res.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR, res.text
102102
assert res.json() == {
@@ -154,7 +154,7 @@ class DependencyInjectionDetailView(DetailViewBaseGeneric):
154154
resource_type = fake.word()
155155
app = build_app(DependencyInjectionDetailView, resource_type=resource_type)
156156
async with AsyncClient(app=app, base_url="http://test") as client:
157-
res = await client.get(f"/users/{user_1.id}", headers={"X-AUTH": "not_admin"})
157+
res = await client.get(f"/users/{user_1.id}/", headers={"X-AUTH": "not_admin"})
158158

159159
assert res.status_code == status.HTTP_403_FORBIDDEN, res.text
160160
assert res.json() == {
@@ -168,7 +168,7 @@ class DependencyInjectionDetailView(DetailViewBaseGeneric):
168168
],
169169
}
170170

171-
res = await client.get(f"/users/{user_1.id}", headers={"X-AUTH": "admin"})
171+
res = await client.get(f"/users/{user_1.id}/", headers={"X-AUTH": "admin"})
172172
assert res.json() == {
173173
"data": {
174174
"attributes": UserAttributesBaseSchema.from_orm(user_1).dict(),
@@ -207,7 +207,7 @@ class DependencyInjectionDetailView(DetailViewBaseGeneric):
207207

208208
app = build_app(DependencyInjectionDetailView, resource_type="test_manipulate_data_layer_kwargs")
209209
async with AsyncClient(app=app, base_url="http://test") as client:
210-
res = await client.get(f"/users/{user_1.id}")
210+
res = await client.get(f"/users/{user_1.id}/")
211211

212212
assert res.status_code == status.HTTP_404_NOT_FOUND, res.text
213213
assert res.json() == {

0 commit comments

Comments
 (0)
Please sign in to comment.