Improve conditional requests support

Prior to this commit, Spring MVC and Spring WebFlux would not support
conditional requests with `If-Match` preconditions. As underlined in the
RFC9110 Section 13.1, those are related to the `If-None-Match`
conditions, but this time only performing requests if the resource
matches the given ETag.

This feature, and in general the `"*"` request Etag, are generally
useful to prevent "lost updates" when performing a POST/PUT request: we
want to ensure that we're updating a version with a known version or
create a new resource only if it doesn't exist already.

This commit adds `If-Match` conditional requests support and ensures
that both `If-Match` and `If-None-Match` work well with `"*"` request
ETags.

We can't rely on `checkNotModified(null)`, as the compiler can't decide
between method variants accepting an ETag `String` or a Last Modified
`long`. Instead, developers should use empty ETags `""` to signal that
no resource is known on the server side.

Closes gh-24881
This commit is contained in:
Brian Clozel
2022-06-21 19:18:33 +02:00
parent a3d3667e64
commit 0783f0762d
7 changed files with 877 additions and 763 deletions

View File

@@ -360,6 +360,12 @@ public final class MockServerHttpRequest extends AbstractServerHttpRequest {
*/
B ifUnmodifiedSince(long ifUnmodifiedSince);
/**
* Set the values of the {@code If-Match} header.
* @param ifMatches the new value of the header
*/
B ifMatch(String... ifMatches);
/**
* Set the values of the {@code If-None-Match} header.
* @param ifNoneMatches the new value of the header
@@ -556,6 +562,12 @@ public final class MockServerHttpRequest extends AbstractServerHttpRequest {
return this;
}
@Override
public BodyBuilder ifMatch(String... ifMatches) {
this.headers.setIfMatch(Arrays.asList(ifMatches));
return this;
}
@Override
public BodyBuilder ifNoneMatch(String... ifNoneMatches) {
this.headers.setIfNoneMatch(Arrays.asList(ifNoneMatches));