Skip to content

Commit 4d8f8bd

Browse files
CosmoVNatalia Grigoreva
authored andcommitted
add ending slash
1 parent 762e91c commit 4d8f8bd

File tree

3 files changed

+15
-13
lines changed

3 files changed

+15
-13
lines changed

fastapi_jsonapi/api.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ def __init__(
7676
pagination_default_limit: Optional[int] = None,
7777
methods: Iterable[str] = (),
7878
max_cache_size: int = 0,
79+
ending_slash: bool = True,
7980
) -> None:
8081
"""
8182
Initialize router items.
@@ -115,6 +116,7 @@ def __init__(
115116
self.schema_detail = schema
116117
# tuple and not set, so ordering is persisted
117118
self.methods = tuple(methods) or self.DEFAULT_METHODS
119+
self.ending_suffix = "/" if ending_slash else ""
118120

119121
if self.type_ in self.all_jsonapi_routers:
120122
msg = f"Resource type {self.type_!r} already registered"
@@ -184,7 +186,7 @@ def _register_get_resource_list(self, path: str):
184186
status.HTTP_200_OK: {"model": self.list_response_schema},
185187
}
186188
self.router.add_api_route(
187-
path=path,
189+
path=path + self.ending_suffix,
188190
tags=self.tags,
189191
responses=list_response_example | self.default_error_responses,
190192
methods=["GET"],
@@ -198,7 +200,7 @@ def _register_post_resource_list(self, path: str):
198200
status.HTTP_201_CREATED: {"model": self.detail_response_schema},
199201
}
200202
self.router.add_api_route(
201-
path=path,
203+
path=path + self.ending_suffix,
202204
tags=self.tags,
203205
responses=create_resource_response_example | self.default_error_responses,
204206
methods=["POST"],
@@ -213,7 +215,7 @@ def _register_delete_resource_list(self, path: str):
213215
status.HTTP_200_OK: {"model": self.detail_response_schema},
214216
}
215217
self.router.add_api_route(
216-
path=path,
218+
path=path + self.ending_suffix,
217219
tags=self.tags,
218220
responses=detail_response_example | self.default_error_responses,
219221
methods=["DELETE"],
@@ -229,7 +231,7 @@ def _register_get_resource_detail(self, path: str):
229231
self.router.add_api_route(
230232
# TODO: variable path param name (set default name on DetailView class)
231233
# TODO: trailing slash (optional)
232-
path=path + "/{obj_id}",
234+
path=path + "/{obj_id}" + self.ending_suffix,
233235
tags=self.tags,
234236
responses=detail_response_example | self.default_error_responses,
235237
methods=["GET"],
@@ -245,7 +247,7 @@ def _register_patch_resource_detail(self, path: str):
245247
self.router.add_api_route(
246248
# TODO: variable path param name (set default name on DetailView class)
247249
# TODO: trailing slash (optional)
248-
path=path + "/{obj_id}",
250+
path=path + "/{obj_id}" + self.ending_suffix,
249251
tags=self.tags,
250252
responses=update_response_example | self.default_error_responses,
251253
methods=["PATCH"],
@@ -264,7 +266,7 @@ def _register_delete_resource_detail(self, path: str):
264266
self.router.add_api_route(
265267
# TODO: variable path param name (set default name on DetailView class)
266268
# TODO: trailing slash (optional)
267-
path=path + "/{obj_id}",
269+
path=path + "/{obj_id}" + self.ending_suffix,
268270
tags=self.tags,
269271
responses=delete_response_example | self.default_error_responses,
270272
methods=["DELETE"],

tests/test_api/test_api_sqla_with_includes.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,15 +1277,15 @@ async def test_create_user_and_fetch_data(self, app: FastAPI, client: AsyncClien
12771277
},
12781278
}
12791279
app.url_path_for("get_user_list")
1280-
res = await client.post("/users", json=create_user_body)
1280+
res = await client.post("/users/", json=create_user_body)
12811281
assert res.status_code == status.HTTP_201_CREATED, res.text
12821282
response_data = res.json()
12831283
assert "data" in response_data, response_data
12841284
assert response_data["data"]["attributes"] == create_user_body["data"]["attributes"]
12851285

12861286
user_id = response_data["data"]["id"]
12871287

1288-
res = await client.get(f"/users/{user_id}")
1288+
res = await client.get(f"/users/{user_id}/")
12891289
assert res.status_code == status.HTTP_200_OK, res.text
12901290
response_data = res.json()
12911291
assert "data" in response_data, response_data
@@ -2511,7 +2511,7 @@ async def test_filters_really_works(
25112511
params = {"filter[name]": fake_name}
25122512
assert user_1.name != fake_name
25132513
assert user_2.name != fake_name
2514-
res = await client.get("/users", params=params)
2514+
res = await client.get("/users/", params=params)
25152515
assert res.status_code == status.HTTP_200_OK, res.text
25162516
assert res.json() == {
25172517
"data": [],

tests/test_api/test_routers.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class DependencyInjectionDetailView(DetailViewBaseGeneric):
8989

9090
app = build_app(DependencyInjectionDetailView, resource_type="test_dependency_handler_call")
9191
async with AsyncClient(app=app, base_url="http://test") as client:
92-
res = await client.get("/users/1")
92+
res = await client.get("/users/1/")
9393

9494
assert res.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR, res.text
9595
assert res.json() == {
@@ -149,7 +149,7 @@ class DependencyInjectionDetailView(DetailViewBaseGeneric):
149149
resource_type = "test_dependencies_as_permissions"
150150
app = build_app(DependencyInjectionDetailView, resource_type=resource_type)
151151
async with AsyncClient(app=app, base_url="http://test") as client:
152-
res = await client.get(f"/users/{user_1.id}", headers={"X-AUTH": "not_admin"})
152+
res = await client.get(f"/users/{user_1.id}/", headers={"X-AUTH": "not_admin"})
153153

154154
assert res.status_code == status.HTTP_403_FORBIDDEN, res.text
155155
assert res.json() == {
@@ -163,7 +163,7 @@ class DependencyInjectionDetailView(DetailViewBaseGeneric):
163163
],
164164
}
165165

166-
res = await client.get(f"/users/{user_1.id}", headers={"X-AUTH": "admin"})
166+
res = await client.get(f"/users/{user_1.id}/", headers={"X-AUTH": "admin"})
167167
assert res.json() == {
168168
"data": {
169169
"attributes": UserAttributesBaseSchema.model_validate(user_1).model_dump(),
@@ -203,7 +203,7 @@ class DependencyInjectionDetailView(DetailViewBaseGeneric):
203203

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

208208
assert res.status_code == status.HTTP_404_NOT_FOUND, res.text
209209
assert res.json() == {

0 commit comments

Comments
 (0)