Closes #21356: Implement ETag support for REST API #279

Closed
opened 2026-04-05 16:24:30 +02:00 by MrUnknownDE · 0 comments
Owner

Originally created by @jeremystretch on 2/25/2026

Closes: #21356

netbox/netbox/api/viewsets/__init__.py

  1. ETagMixin class (new, lines 37–56): Static helper _get_etag() returns a quoted ISO 8601 ETag derived from last_updated (falling back to created). The retrieve() override appends the ETag header to detail responses.
  2. NetBoxReadOnlyModelViewSet and NetBoxModelViewSet: ETagMixin added as the first base class, giving its retrieve() priority in the MRO over DRF's RetrieveModelMixin.retrieve().
  3. update(): Added an If-Match precondition check per RFC 9110 §13.1.1 — if the header is present and not *, it compares against the current ETag and returns 412 Precondition Failed on mismatch. The response now includes a
    fresh ETag reflecting the updated last_updated value.
  4. create(): Single-object creation responses now include an ETag header. Bulk creation responses do not (no single canonical object).

netbox/utilities/testing/api.py

  1. test_get_object(): After the 200 OK assertion, verifies that ChangeLoggingMixin models return an ETag header.
  2. test_update_object_with_etag() (new method): End-to-end test that verifies correct-ETag PATCH returns 200 with a changed ETag, and stale-ETag PATCH returns 412.
*Originally created by @jeremystretch on 2/25/2026* ### Closes: #21356 #### `netbox/netbox/api/viewsets/__init__.py` 1. ETagMixin class (new, lines 37–56): Static helper `_get_etag()` returns a quoted ISO 8601 ETag derived from last_updated (falling back to created). The retrieve() override appends the ETag header to detail responses. 2. NetBoxReadOnlyModelViewSet and NetBoxModelViewSet: ETagMixin added as the first base class, giving its `retrieve()` priority in the MRO over DRF's `RetrieveModelMixin.retrieve()`. 3. `update()`: Added an If-Match precondition check per RFC 9110 §13.1.1 — if the header is present and not *, it compares against the current ETag and returns 412 Precondition Failed on mismatch. The response now includes a fresh ETag reflecting the updated last_updated value. 4. `create()`: Single-object creation responses now include an ETag header. Bulk creation responses do not (no single canonical object). #### `netbox/utilities/testing/api.py` 1. `test_get_object()`: After the 200 OK assertion, verifies that ChangeLoggingMixin models return an ETag header. 2. `test_update_object_with_etag()` (new method): End-to-end test that verifies correct-ETag PATCH returns 200 with a changed ETag, and stale-ETag PATCH returns 412.
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github/netbox#279