Skip to content

Instantly share code, notes, and snippets.

@astorm
Last active August 29, 2015 14:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save astorm/11a3065feca127ae18c3 to your computer and use it in GitHub Desktop.
Save astorm/11a3065feca127ae18c3 to your computer and use it in GitHub Desktop.

The worst one act play ever.

New User:   Hello Magento Site, give me a catalog listing page

Varnish:    Someone wants a page, do I have it cached?  Yes! Since I
            have it cached, I don't need to talk to Magento, I can just sent
            the user this page.

            [Varnish grabs the page]

            Also, since there's no form key, I'll send back a newly generated 
            session ID!  I'm so smart!

            Uh oh, ESI includes.  Better ask my ESI sub-routines to
            handle those.  Hey ESI, here's a page.

ESI:        Hmmm, looks like this cached page has ESI includes on
            it. I'll need to fetch those parts from Magento after all.  I
            don't have a frontend session ID to send, so I'll send along a
            newly generated session ID.  I'm so smart!

ESI:        Hey Magento!  Give me a form key. (Also, here's a newly        
            generated frontend session ID)

Magento:    OK, here's a form key.  Also, here's a cookie with the        
            session ID set.  If you use this frontend session id again I'll
            give you the same form key.

ESI:        Hey Magento!  Give me another form key (Also, here's a    
            newly generated frontend session ID)

Magento:    Um, ok.  That's a different frontend session ID, but
            here's a new form key. Also, here's a cookie with the session ID
            set.

            etc...

ESI:        OK Varnish, all ESI includes replaced

Varnish:    Great work ESI, now I'll send the page back, and I'll    
            send it back with that first frontend session ID cookie so that
            future requests will use the same thing.            

So, varnish correctly generates the session id. The underlying problem here is, for the first request only, varnish will not use that generated session ID cookie for the ESI request. The ESI requests seem to look at the original request. The creates problems if that first page has CSRF form key protections.

@melvyn-sopacua
Copy link

I'll have a look at the VCL.

PS. Real funny, I just wrote a Bob & Alice dialog about the locking of the configuration cache.

@melvyn-sopacua
Copy link

Here's my loose thoughts, should have some pointers on where you could insert logging:

Thinking out load:

if (req.http.X-Varnish-Esi-Access == "private" &&
                        req.http.Cookie ~ "frontend=") {

That private access probably isn't known here yet, or forgotten.

set req.http.X-Varnish-Esi-Access = regsub(
    req.url, ".*/{{esi_cache_type_param}}/(\w+)/.*", "\1");

Saw this in a commit. What did this fix and what sets the value?

if (req.http.Cookie !~ "frontend=" && !req.http.X-Varnish-Esi-Method) {
    if (client.ip ~ crawler_acl ||
            req.http.User-Agent ~ "^(?:{{crawler_user_agent_regex}})$") {
        # it's a crawler, give it a fake cookie
        set req.http.Cookie = "frontend=crawler-session";
    } else {
        # it's a real user, make up a new session for them
        call generate_session;
    }
}

Does it get back here? Are all variables still in tact then?

if ({{force_cache_static}} &&

I generally dislike paramaters with "force" in them. It's an insult to Yoda.

All this logic in vcl_hash, has a high potential of a case not being considered.
Especially since you'd think this makes 2 round trips but it really doesn't.

It's a:

local read =>  parse => net read => replace => response

But does it stay in the same thread / process and is everything reset so that
the same rules apply?

@melvyn-sopacua
Copy link

PS. Why even have all this logic to not send or do send that frontend coookie. Just send it, doesn't even matter where it comes from. Any ESI request shall have an oreo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment