From 1cd836a05c0b45aa843ff26e38a4a4ead754ff7c Mon Sep 17 00:00:00 2001 From: German Bernadskiy Date: Fri, 20 Dec 2024 20:34:48 +1000 Subject: [PATCH] added option --- fastapi_jsonapi/api.py | 14 ++++++++------ tests/test_api/test_api_sqla_with_includes.py | 6 +++--- tests/test_api/test_routers.py | 8 ++++---- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/fastapi_jsonapi/api.py b/fastapi_jsonapi/api.py index 9fbdfd40..e367899f 100644 --- a/fastapi_jsonapi/api.py +++ b/fastapi_jsonapi/api.py @@ -79,6 +79,7 @@ def __init__( pagination_default_limit: Optional[int] = None, methods: Iterable[str] = (), max_cache_size: int = 0, + ending_slash: bool = True, ) -> None: """ Initialize router items. @@ -118,6 +119,7 @@ def __init__( self.schema_detail = schema # tuple and not set, so ordering is persisted self.methods = tuple(methods) or self.DEFAULT_METHODS + self.ending_suffix = "/" if ending_slash else "" if self.type_ in self.all_jsonapi_routers: msg = f"Resource type {self.type_!r} already registered" @@ -187,7 +189,7 @@ def _register_get_resource_list(self, path: str): status.HTTP_200_OK: {"model": self.list_response_schema}, } self._router.add_api_route( - path=path, + path=path + self.ending_suffix, tags=self._tags, responses=list_response_example | self.default_error_responses, methods=["GET"], @@ -201,7 +203,7 @@ def _register_post_resource_list(self, path: str): status.HTTP_201_CREATED: {"model": self.detail_response_schema}, } self._router.add_api_route( - path=path, + path=path + self.ending_suffix, tags=self._tags, responses=create_resource_response_example | self.default_error_responses, methods=["POST"], @@ -216,7 +218,7 @@ def _register_delete_resource_list(self, path: str): status.HTTP_200_OK: {"model": self.detail_response_schema}, } self._router.add_api_route( - path=path, + path=path + self.ending_suffix, tags=self._tags, responses=detail_response_example | self.default_error_responses, methods=["DELETE"], @@ -232,7 +234,7 @@ def _register_get_resource_detail(self, path: str): self._router.add_api_route( # TODO: variable path param name (set default name on DetailView class) # TODO: trailing slash (optional) - path=path + "/{obj_id}", + path=path + "/{obj_id}" + self.ending_suffix, tags=self._tags, responses=detail_response_example | self.default_error_responses, methods=["GET"], @@ -248,7 +250,7 @@ def _register_patch_resource_detail(self, path: str): self._router.add_api_route( # TODO: variable path param name (set default name on DetailView class) # TODO: trailing slash (optional) - path=path + "/{obj_id}", + path=path + "/{obj_id}" + self.ending_suffix, tags=self._tags, responses=update_response_example | self.default_error_responses, methods=["PATCH"], @@ -267,7 +269,7 @@ def _register_delete_resource_detail(self, path: str): self._router.add_api_route( # TODO: variable path param name (set default name on DetailView class) # TODO: trailing slash (optional) - path=path + "/{obj_id}", + path=path + "/{obj_id}" + self.ending_suffix, tags=self._tags, responses=delete_response_example | self.default_error_responses, methods=["DELETE"], diff --git a/tests/test_api/test_api_sqla_with_includes.py b/tests/test_api/test_api_sqla_with_includes.py index 0ea5ab9d..9c4aa182 100644 --- a/tests/test_api/test_api_sqla_with_includes.py +++ b/tests/test_api/test_api_sqla_with_includes.py @@ -1525,7 +1525,7 @@ async def test_create_user_and_fetch_data(self, app: FastAPI, client: AsyncClien }, } app.url_path_for("get_user_list") - res = await client.post("/users", json=create_user_body) + res = await client.post("/users/", json=create_user_body) assert res.status_code == status.HTTP_201_CREATED, res.text response_data = res.json() assert "data" in response_data, response_data @@ -1533,7 +1533,7 @@ async def test_create_user_and_fetch_data(self, app: FastAPI, client: AsyncClien user_id = response_data["data"]["id"] - res = await client.get(f"/users/{user_id}") + res = await client.get(f"/users/{user_id}/") assert res.status_code == status.HTTP_200_OK, res.text response_data = res.json() assert "data" in response_data, response_data @@ -2746,7 +2746,7 @@ async def test_filters_really_works( params = {"filter[name]": fake_name} assert user_1.name != fake_name assert user_2.name != fake_name - res = await client.get("/users", params=params) + res = await client.get("/users/", params=params) assert res.status_code == status.HTTP_200_OK, res.text assert res.json() == { "data": [], diff --git a/tests/test_api/test_routers.py b/tests/test_api/test_routers.py index c6b62250..b086a2aa 100644 --- a/tests/test_api/test_routers.py +++ b/tests/test_api/test_routers.py @@ -96,7 +96,7 @@ class DependencyInjectionDetailView(DetailViewBaseGeneric): app = build_app(DependencyInjectionDetailView, resource_type="test_dependency_handler_call") async with AsyncClient(app=app, base_url="http://test") as client: - res = await client.get("/users/1") + res = await client.get("/users/1/") assert res.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR, res.text assert res.json() == { @@ -154,7 +154,7 @@ class DependencyInjectionDetailView(DetailViewBaseGeneric): resource_type = fake.word() app = build_app(DependencyInjectionDetailView, resource_type=resource_type) async with AsyncClient(app=app, base_url="http://test") as client: - res = await client.get(f"/users/{user_1.id}", headers={"X-AUTH": "not_admin"}) + res = await client.get(f"/users/{user_1.id}/", headers={"X-AUTH": "not_admin"}) assert res.status_code == status.HTTP_403_FORBIDDEN, res.text assert res.json() == { @@ -168,7 +168,7 @@ class DependencyInjectionDetailView(DetailViewBaseGeneric): ], } - res = await client.get(f"/users/{user_1.id}", headers={"X-AUTH": "admin"}) + res = await client.get(f"/users/{user_1.id}/", headers={"X-AUTH": "admin"}) assert res.json() == { "data": { "attributes": UserAttributesBaseSchema.from_orm(user_1).dict(), @@ -207,7 +207,7 @@ class DependencyInjectionDetailView(DetailViewBaseGeneric): app = build_app(DependencyInjectionDetailView, resource_type="test_manipulate_data_layer_kwargs") async with AsyncClient(app=app, base_url="http://test") as client: - res = await client.get(f"/users/{user_1.id}") + res = await client.get(f"/users/{user_1.id}/") assert res.status_code == status.HTTP_404_NOT_FOUND, res.text assert res.json() == {