spring-projects / spring-projects/spring-data-rest
Auto-populated Last-Modified header does not consider projections [DATAREST-613]
@odrotbohm is already working on this.
Since Dec 31, 2020.
- Dominant language
- Java
- Stars
- 958
- Forks
- 568
- PR merge metrics
- No merged PRs in 30d
Description
Chris Beams opened DATAREST-613 and commented
DATAREST-471 introduced support for auto-populating the Last-Modified header based on @LastModifiedDate auditing metadata. This works well for simple GET requests, but breaks down when projections are in the mix.
For example, consider an Assembly entity with a collection of Part entities, each being exposed by their own respective SD REST repositories, e.g.:
$ http localhost:8080/api/assemblies/1
{
"_links": {
"parts": {
"href": "http://localhost:8080/api/assemblies/1/parts"
},
"self": {
"href": "http://localhost:8080/api/assemblies/1"
}
},
"assemblyAttr1": "val1"
"assemblyAttr2": "val2"
}
$ http localhost:8080/api/assemblies/1/parts
{
"_embedded": {
"parts": [
{
"_links": {
"self": {
"href": "http://localhost:8080/api/parts/1"
}
},
"partAttr1": "val1"
"partAttr2": "val2"
},
...
]
},
"_links": {
"self": {
"href": "http://localhost:8080/api/assemblies/1/parts"
}
}
}
Both Assembly and Part are annotated with @LastModifiedDate, meaning that GET requests for individual Assembly or Part resources will respond with a Last-Modified header containing the date that the underlying requested entity was last modified.
Note, however, that a GET request for any collection of assemblies or parts does not respond with a Last-Modified header. That is, collection requests are never cached. This is not optimal from a caching perspective, but at least the client is guaranteed to get the freshest informaton.
But now consider the case of a GET request for an assembly with a projection that includes its parts, e.g.:
$ http localhost:8080/api/assemblies/1?projection=withParts
It's here that we run into trouble. The Last-Modified header will be returned in the response for this request, and it will contain the value of the @LastModifiedDate for the Assembly. If a Part has been added, deleted or updated in the meantime, the client will never know (without a hard-refresh or otherwise clearing or disabling the browser cache).
It seems to me, then, that auto-population of the Last-Modified header should either:
- carefully take projections into account, ensuring that the
Last-Modifiedheader reflects the most recently modified entity included in that projection, or - punt, and avoid populating the
Last-Modifiedheader altogether if one or more projections have been specified in the query string. Basically, treat requests for projections like requests for collections are already treated.
Barring a quick implementation of either of the above, a stopgap measure would be to provide a way to disable auto-population of the Last-Modified header. Based on my reading of the implementation of this feature, I couldn't find a way to do it. I'm looking at stripping the header out with a Filter at this point
Affects: 2.4 M1 (Gosling)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.