412 Precondition Failed
In HTTP it’s possible to do conditional requests. These are requests that only execute if the right conditions are met.
For 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.
Examples
This client only wants the PUT
request to succeed, if it didn’t already
exist:
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 changed 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 conflicts when multiple people are writing to the same resource and overwriting each other’s changes. This is also known as the ‘lost update problem’.
Using the 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 GET
request.
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.
References
- RFC7232, Section 4.2 - 412 Precondition Failed.
- RFC7240, Section 4.2 -
Prefer: return=representation
. - RFC8144, Section 3.2 - Usage of
Prefer: return=representation
with 412.