Problem/Motivation
#2471473: REST responses should have proper cache tags ensured entity cacheability metadata is present. Dealing with entity & field access was deferred to an undefined follow-up. We should fix this ASAP because it could expose sensitive information for sites with complex entity access.
(Note that the user.permissions cache context is present by default, due to a permission being required to access any of the REST routes. This is why it's okay for this to be handled in the public issue queue.)
Proposed resolution
Associate entity & field access cacheability metadata with the response.
Remaining tasks
None.
User interface changes
None.
API changes
None.
Data model changes
None.
Original report
I jumped from beta5 top beta10 with a custom simple REST endpoint module, basically following this http://enzolutions.com/articles/2014/12/16/how-to-create-a-rest-resource...
My custom endpoint /rest/articles/get returns nids of all articles.
It worked and works fine, but since some update, stale content is being served.
When I clear the Drupal cache, my endpoints returns the new nids, so it must be a cache thing.
I suspect it has something to do with the finished support for cache-tags altough #2471473: REST responses should have proper cache tags claims it has been fixed in REST output.
Now for the weird part:
When I retrieve data from the same endpoint through Chrome's Dev HTTP Client, the results are up to date! (btw: I see "X-Drupal-Cache-Tags: config:rest.settings" in the headers for the response).
So what's going on here? How do I get fresh results when using guzzle as a http client? I've ruled out browser caching.
| Comment | File | Size | Author |
|---|---|---|---|
| #24 | rest_entity_access_cacheability-2485683-24.patch | 4.7 KB | wim leers |
Comments
Comment #1
askibinski commentedDid some more debugging, when I perform the request through JS instead of Guzzle and add the cache: false option, I get the fresh results like in Dev HTTP Client:
Above code for javascript is similar to adding a timestamp parameter to your query in Guzzle.
But I would prefer my custom rest endpoint cache to be updated when the results change. Any documentation on how to do that?
Comment #2
clemens.tolboomComment #3
clemens.tolboomSome questions:
How does wget / curl respond?
Are you logged in?
Can you share your guzzle code on ie github?
Comment #4
askibinski commentedcurl also receives fresh content:
Here is the guzzle code.
update: the curl code uses authentication but it does not matter, if I enter "0" as username and leave password empty I still get fresh results through curl/dev client. But not so in php/js from the client. (unless I force to disable cache bij adding the cache parameter which adds a timestamp).
I'm pretty sure this has something to do with the new cachetags but I'm not sure how to use the cache api in order to make sure Drupal invalidates this particular cache entry when a new node is posted.
Comment #5
clemens.tolboomAdded a link to 'stale content'
Comment #6
wim leersThe problems described in the issue so far sound like browser caching, plain & simple. If the response have a
Cache-Control: max-age=60header for example, the browser is going to cache the response for a minute, regardless of cache tags being invalidated. Cache tags can only invalidate responses on the server, not on the client.But, I'm going to repurpose this issue for something closely related, because in
EntityResourcethere's at least this problem wrt cacheability:So, I'll take a look at improving this.
Comment #7
wim leersComment #8
wim leersComment #9
wim leersThe fix was trivial, it took me far more time to write test coverage. (Rolled against 8.1 but should apply cleanly to 8.0 too.)
Comment #10
wim leersComment #11
wim leersComment #13
wim leersUnrelated test failures due to pre-existing tests asserting the expected cacheability metadata for the
field_test_textfield, which I changed here to have something to detect:I'll work on addressing those.
Comment #14
neclimdulOh wow. Going to have to work to wrap my head around that.
Skim:
NULL
:-D
Comment #15
joshi.rohit100NUL1 ?
Comment #16
wim leerslol lol lol
I'm a moron.
Comment #17
wim leersFirst, fix the plain stupid things.
Comment #18
wim leersI can't reproduce the failure in
Drupal\rest\Tests\ReadTest. :(Let's hope #17 will only have failures in
Drupal\system\Tests\Entity\FieldAccessTest— the failures there I can reproduce.Comment #20
wim leersThis fixes the remaining failure.
Interdiff explanation: Rather than modifying
EntityTestAccessControlHandler, I'm now just adding one more special value toentity_test_entity_field_access()to test for. In doing so, I have to useaddCacheableDependency(). The surrounding code is still using the deprecatedcacheUntilEntityChanges(). I think it's in scope here to update them.Comment #21
dawehner+1 for a more explicit value.
Comment #22
catchAre there three s on purpose? Looks like a typo that got copied everywhere.
Comment #23
wim leersYep, that's a typo. Fixing.
Comment #24
wim leersComment #25
dawehnerHe, good spot.
Comment #26
catchFor a minute I though it was a llama -> snake switch.
Committed/pushed to 8.1.x and cherry-picked to 8.0.x. Thanks!
Comment #29
wim leers:P
LLAMAS FOREVER <3 <3