Force Views ajax paging to use GET instead of POST so it can be cached.

Events happening in the community are now at Drupal community events on www.drupal.org.
scottatdrake's picture

After witnessing some dramatic CPU spikes, I've discovered that Views' ajax paging sends requests via POST instead of GET (very large POSTs!), preventing them from being cached by Varnish and the like.

Evidently, I'm not the only one that has encountered this but I haven't found any solutions.

Any ideas?

Comments

Alternatively you could edit

dalin's picture

Alternatively you could edit your .vcl file

--


Dave Hansen-Lange
Director of Technical Strategy, Advomatic.com
Pronouns: he/him/his

I agree with Dalin. Varnish

Michael Hofmockel's picture

I agree with Dalin. Varnish seems to be your problem here not Views. Much easier to manage a varnish config file than a submodule or worse a forked views module.

Regards,
Michael Hofmockel

Open Source || Open Access || Open Mind

Edit the .vcl to do what?

scottatdrake's picture

Edit the .vcl to do what? The issue is that Varnish can't cache POSTs. (Unless I'm missing something obvious!)

Some background... As I understand it, the Drupal ajax framework sends requests via POSTs because they are so large (like 5,000k-15,000k+) and doing so with GET would quickly overrun URL character limits.

Varnish (correctly, IMO) assumes that POST requests are sending changes to data, and passes them through. I think Varnish has it right and Drupal should be using GET but, easier said than done. The size of the requests would have to come way down.

Related D8 thread: Ensure it is possible to use AJAX with GET requests

I'm all for reducing the size

dalin's picture

I'm all for reducing the size of the requests and switching Views AJAX to use GET, but Varnish can cache POST requests.

If in your default.vcl vcl_recv looks like:

sub vcl_recv {
  // various rules.
}

Then the default vcl_recv will be appended to your custom version. If instead you have:

sub vcl_recv {
  // various rules.
  return (lookup);
}

then the default vcl_recv will be skipped.

In that default there's a section like this:

  if (req.request != "GET" && req.request != "HEAD") {
      /* We only deal with GET and HEAD by default */
      return (pass);
  }

You can copy this into your default.vcl with some modifications. Something along the lines of

if (req.request != "GET" &&
    req.request != "HEAD"
    !(req.request = "POST" && /* some check for whatever is unique about these views ajax calls /)) {
      /
We only deal with GET and HEAD by default */
      return (pass);
  }

--


Dave Hansen-Lange
Director of Technical Strategy, Advomatic.com
Pronouns: he/him/his

Ah ha

scottatdrake's picture

Okay, iiiinteresting. I'll take a closer look at this approach. Thanks a lot!

This seems really promising

scottatdrake's picture

This seems really promising but I don't know if there is anything unique about the views ajax calls that Varnish can see.

They all POST to "/views/ajax/". Everything distinguishing about them seems to be buried in the request body, which isn't available to the vcl. At least not without "dirty hacks" or mods, according to that guy.

They're also sent with "Cache-Control: no-cache, must-revalidate" headers-- but I figure that's a separate issue.

Old thread, but I've found a

leon kessler's picture

Old thread, but I've found a way to get Views to work with GET. It requires an override of a core JavaScript function.
Have put it in a module here: https://drupal.org/sandbox/leonnk/2232463

High performance

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: