-
Notifications
You must be signed in to change notification settings - Fork 16
Description
Hi there!
I noticed that sometimes I'm needing to repeat a bunch of code to handle sending/processing ETag / Last-Modified / If-Match / If-Unmodified-Since headers and I was wondering if that's something that could potentially be generated instead?
I did take a look around the issues/documentation and couldn't see anything for this already but I did notice that this is almost the opposite of #632 😆
An example could be:
@Controller
@Path("/contacts")
class ContactController {
@Get("/{id}")
@CacheControl("getByIdCacheControl") // The name of the method on the controller that handles the cache control
Contact getById(long id) {
...
}
// Mirrors the arguments of the original method
CacheManagement getByIdCacheControl(long id) {
return CacheManagement.builder()
.lastModified(...) // OffsetDateTime maybe?
.etag(...) // String maybe? Or perhaps building up a hash internally?
.maxAge(..) // For `Cache-Control` - `Duration` maybe? And could be used to automatically create the `Expires` header?
// Other methods could exist for the `Cache-Control` header like `privateOnly`, `sMaxAge`/`sharedCacheMaxAge`,`staleIfError`
.build();
}
@Patch
@ConditionalRequest("saveConditional")
// @ConditionalRequest(methodName = "saveConditional", acceptIfMissingHeaders = false)
void save(Contact contact) {
...
}
// Mirrors the arguments of the original method
ConditionalRequestManagement saveConditional(Contact contact) {
return ConditionalRequestManagement.builder()
.etag(..) // named to reflect what the server sent on a GET or HEAD request, even though this doesn't reflect the inbound header...
.lastModified(..)
.build();
}
}And then the generated controller automatically handles setting the headers correctly, as well as replying with the appropriate 304 or 412 statuses by calling the other method first. So the flow would be:
For @CacheControl (GET):
- Call the management method to get the policy (
ETag/Last-Modified). - Check request headers (
If-None-Match/If-Modified-Since). - Hit: Return
304 Not Modifiedimmediately. - Miss: Execute the controller method, and apply the
Cache-Control,ETag, andLast-Modifiedheaders.
For @ConditionalRequest (PUT/PATCH/etc):
- Call the management method to get the current resource state.
- Check request headers (
If-Match/If-Unmodified-Since). - Mismatch: Return
412 Precondition Failedimmediately. - Match: Execute the controller method (save/update).
It could have just the one annotation and "Management" object, and the names could definitely be improved from my example, but is this idea (once fleshed out a bit more) something that could be in-scope for avaje-http?