Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(caching): Support caching of GET requests #1197

Merged
merged 7 commits into from
May 20, 2022

Conversation

larowlan
Copy link
Contributor

@larowlan larowlan commented May 6, 2021

Fixes #1196

Copy link
Contributor

@Kingdutch Kingdutch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would we be able to simplify this since Drupal core's CommandLineOrUnsafeMethod already prevents caching of non-HEAD/GET requests (since the HTTP standard discourages it). I think relying on Drupal core's behaviour here is fine, if someone for some reason has overwritten this then they probably know what they're doing or we can't help them anyway.

That would mean we can remove DenyPost and the service definition and changing the RouterProvider with the added test coverage would be sufficient.

Comment on lines 95 to 103
protected function configureCachePolicy(int $max_age = 900) {
$this->container->set('dynamic_page_cache_request_policy', (new ChainRequestPolicy())
->addPolicy(new DenyPost()));
$this->container->set('page_cache_request_policy', (new ChainRequestPolicy())
->addPolicy(new NoSessionOpen($this->container->get('session_configuration')))
->addPolicy(new DenyPost()));
// Turn on caching.
$this->config('system.performance')->set('cache.page.max_age', $max_age)->save();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed in the test? Kernel tests install the graphql module and it should load the services for core and the module on its own. I believe configuring this in the test bypasses actually testing our configuration (i.e. removing the module's service definition could still let the test pass even though we may not want it to).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, it is needed - as per the comment core adds in the CommandLineOrUnsafeMethod by default which means in the test it is always DENY because kernel tests are command line based

All this is doing is recreating those services, but without CommandLineOrUnsafeMethod

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, I could write these tests as a functional test, but I didn't know if there was a reason the module didn't have any yet, so didn't want to introduce one without checking

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I get for doing reviews at 8 AM without coffee. Totally missing a wonderfully written comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

@klausi klausi added the 4.x label Jul 3, 2021
Copy link
Contributor

@klausi klausi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I'm wondering why we had no_cache in the first place on our routes.

Could there be a scenario where the page cache would behave unexpectedly? Thinking of problems where private information of one user gets into the page cache and is then served to other users. But I think that should be covered by our cache metadata. We should check that the defaults are set up correctly or if we also need to do something there.

@larowlan
Copy link
Contributor Author

larowlan commented Jul 4, 2021

thanks @klausi - pushed those changes

in terms of caching, the resolvers need to take care of adding all the required metadata

this includes for the query too, e.g. cache context url.params.query needs to be added.

we could do this by default if it was something everything needed - thoughts?

can you trigger a test run?

@acbramley
Copy link
Contributor

What's outstanding to get this over the line? I'm looking at migrating from JSON:API to GraphQL and caching would be one of the top priorities in making that decision.

Copy link
Contributor

@Kingdutch Kingdutch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to have this committed :D

It's indeed the responsibility of all the resolvers of providing proper cacheability information. All the logic in the GraphQL module already exists to collect and propagate that.

With the insights I've gained in the past months I don't see this change as being much different from what happens already for POST'ed queries (i.e. if this would leak private info, so would our current POST implementations). Because although we do not cache at the request level, we cache with the exact same information at the result level.

Copy link
Contributor

@klausi klausi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also double-checked this and look good to me! GET requests use query parameters to pass the GraphQL query that would be in the POST body otherwise. Page caches like Varnish should take URL query parameters into account, so that should also not be a problem here.

Thank you!

@klausi klausi merged commit d1fc8d7 into drupal-graphql:8.x-4.x May 20, 2022
klausi pushed a commit to klausi/graphql that referenced this pull request Sep 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[4.x] Make GET requests cacheable
4 participants