In HTTP it’s possible to do conditional requests. These are requests that only execute if the right conditions are met.
GET requests, this might be done to only retrieve the resource if it has
changed. For those cases
304 Not Modified is returned.
For other cases,
412 Precondition Failed is returned.
This client only wants the
PUT request to succeed, if it didn’t already
PUT /foo/new-article.md HTTP/1.1 Content-Type: text/markdown If-None-Match: *
This request is an update, and it should only succeed if the article hasn’t change since last time.
PUT /foo/old-article.md HTTP/1.1 If-Match: "1345-12315" Content-Type: text/markdown
If the condition didn’t pass, it returns:
HTTP/1.1 412 Precondition Failed Content-Type: text/plain The article you're tring to update has changed since you last seen it.
One great advantage of this is that prevents lost updates, due to multiple people writing to the same resource. This is also known as the ‘lost update’ problem.
Prefer header, it’s possible for a client to get the current
state of the resource, in case the local copy was outdated. This saves a
PUT /foo/old-article.md HTTP/1.1 If-Match: "1345-12315" Content-Type: text/markdown Prefer: return=representation ### Article version 2.1
HTTP/1.1 412 Precondition Failed Content-Type: text/markdown Etag: "4444-12345" Vary: Prefer ### Article version 3.0
This is useful, but it should probably have been designed with a HTTP/2 Push message instead. Nevertheless, there’s no harm in adopting this for legacy HTTP/1.1 systems.
- RFC7232, Section 4.2 - 412 Precondition Failed.
RFC7240, Section 4.2 -
RFC8144, Section 3.2 - Usage of
Prefer: return=representationwith 412.