Skip to content

Commit b0f46db

Browse files
committed
Fix Item PUT endpoint per #385
1 parent 54b3d6d commit b0f46db

File tree

5 files changed

+38
-15
lines changed

5 files changed

+38
-15
lines changed

stac_fastapi/extensions/stac_fastapi/extensions/core/transaction.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,15 @@
1616

1717

1818
@attr.s
19-
class PostOrPutItem(CollectionUri):
20-
"""Create or update Item."""
19+
class PostItem(CollectionUri):
20+
"""Create Item."""
21+
22+
item: stac_types.Item = attr.ib(default=Body())
23+
24+
25+
@attr.s
26+
class PutItem(ItemUri):
27+
"""Update Item."""
2128

2229
item: stac_types.Item = attr.ib(default=Body())
2330

@@ -84,20 +91,20 @@ def register_create_item(self):
8491
response_model_exclude_unset=True,
8592
response_model_exclude_none=True,
8693
methods=["POST"],
87-
endpoint=self._create_endpoint(self.client.create_item, PostOrPutItem),
94+
endpoint=self._create_endpoint(self.client.create_item, PostItem),
8895
)
8996

9097
def register_update_item(self):
9198
"""Register update item endpoint (PUT /collections/{collection_id}/items)."""
9299
self.router.add_api_route(
93100
name="Update Item",
94-
path="/collections/{collection_id}/items",
101+
path="/collections/{collection_id}/items/{item_id}",
95102
response_model=Item if self.settings.enable_response_models else None,
96103
response_class=self.response_class,
97104
response_model_exclude_unset=True,
98105
response_model_exclude_none=True,
99106
methods=["PUT"],
100-
endpoint=self._create_endpoint(self.client.update_item, PostOrPutItem),
107+
endpoint=self._create_endpoint(self.client.update_item, PutItem),
101108
)
102109

103110
def register_delete_item(self):

stac_fastapi/pgstac/stac_fastapi/pgstac/transactions.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,22 @@ async def create_item(
4040
return item
4141

4242
async def update_item(
43-
self, collection_id: str, item: stac_types.Item, **kwargs
43+
self, collection_id: str, item_id: str, item: stac_types.Item, **kwargs
4444
) -> Optional[Union[stac_types.Item, Response]]:
4545
"""Update item."""
46-
item_collection_id = item.get("collection")
47-
if item_collection_id is not None and collection_id != item_collection_id:
46+
body_collection_id = item.get("collection")
47+
if body_collection_id is not None and collection_id != body_collection_id:
4848
raise HTTPException(
4949
status_code=409,
50-
detail=f"Collection ID from path parameter ({collection_id}) does not match Collection ID from Item ({item_collection_id})",
50+
detail=f"Collection ID from path parameter ({collection_id}) does not match Collection ID from Item ({body_collection_id})",
5151
)
5252
item["collection"] = collection_id
53+
body_item_id = item["id"]
54+
if body_item_id != item_id:
55+
raise HTTPException(
56+
status_code=409,
57+
detail=f"Item ID from path parameter ({item_id}) does not match Item ID from Item ({body_item_id})",
58+
)
5359
request = kwargs["request"]
5460
pool = request.app.state.writepool
5561
await dbfunc(pool, "update_item", item)

stac_fastapi/pgstac/tests/api/test_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"POST /collections",
2020
"POST /collections/{collection_id}/items",
2121
"PUT /collections",
22-
"PUT /collections/{collection_id}/items",
22+
"PUT /collections/{collection_id}/items/{item_id}",
2323
]
2424

2525

stac_fastapi/pgstac/tests/clients/test_postgres.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ async def test_update_item(app_client, load_test_collection, load_test_item):
7676

7777
item.properties.description = "Update Test"
7878

79-
resp = await app_client.put(f"/collections/{coll.id}/items", content=item.json())
79+
resp = await app_client.put(
80+
f"/collections/{coll.id}/items/{item.id}", content=item.json()
81+
)
8082
assert resp.status_code == 200
8183

8284
resp = await app_client.get(f"/collections/{coll.id}/items/{item.id}")

stac_fastapi/pgstac/tests/resources/test_item.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,9 @@ async def test_update_item(
137137

138138
item.properties.description = "Update Test"
139139

140-
resp = await app_client.put(f"/collections/{coll.id}/items", content=item.json())
140+
resp = await app_client.put(
141+
f"/collections/{coll.id}/items/{item.id}", content=item.json()
142+
)
141143
assert resp.status_code == 200
142144

143145
resp = await app_client.get(f"/collections/{coll.id}/items/{item.id}")
@@ -158,8 +160,10 @@ async def test_update_item_mismatched_collection_id(
158160
in_json["collection"] = random.choice(ascii_letters)
159161
assert in_json["collection"] != coll.id
160162

163+
item_id = in_json["id"]
164+
161165
resp = await app_client.put(
162-
f"/collections/{coll.id}/items",
166+
f"/collections/{coll.id}/items/{item_id}",
163167
json=in_json,
164168
)
165169
assert resp.status_code == 409
@@ -252,7 +256,9 @@ async def test_update_new_item(
252256
item = load_test_item
253257
item.id = "test-updatenewitem"
254258

255-
resp = await app_client.put(f"/collections/{coll.id}/items", content=item.json())
259+
resp = await app_client.put(
260+
f"/collections/{coll.id}/items/{item.id}", content=item.json()
261+
)
256262
assert resp.status_code == 404
257263

258264

@@ -263,7 +269,9 @@ async def test_update_item_missing_collection(
263269
item = load_test_item
264270
item.collection = None
265271

266-
resp = await app_client.put(f"/collections/{coll.id}/items", content=item.json())
272+
resp = await app_client.put(
273+
f"/collections/{coll.id}/items/{item.id}", content=item.json()
274+
)
267275
assert resp.status_code == 200
268276

269277
put_item = resp.json()

0 commit comments

Comments
 (0)