Put That Appends

A cart API exposes this endpoint. The client sends the request, the server commits it, and then the response is lost to a dropped connection, so the client re-sends the byte-identical request.

PUT /v1/carts/8821/items HTTP/1.1
Host: api.shop.example
Content-Type: application/json

{"sku": "TSH-91", "qty": 2}
HTTP/1.1 200 OK
Content-Type: application/json

{"items": [{"sku": "TSH-91", "qty": 2}]}

The handler runs INSERT INTO cart_items (cart_id, sku, qty) VALUES (...) and the table has no unique constraint on (cart_id, sku). What is the cart after the retry, and what does that say about the design?

A

Two rows totalling qty 4, and that is fine. RFC 9110 requires idempotence only for DELETE.

B

Two rows totalling qty 4. The handler appends, so this operation is not idempotent, and the method is lying about it. Either make the handler set the item's quantity, or move the append to POST.

C

One row, qty 2. PUT is idempotent per RFC 9110, so the second request is a no-op.

D

One row, qty 2. The 200 response with no Location header tells the client the resource already existed, so the retry is treated as a refresh.