Set cookie on redirect

I have a view (confirm password) that sets a cookie and then redirects (302) to another view (change email).

It took me quite a lot of time, but I finally could reproduce the error I have:

Looking at the browser storage panel, one can see that the cookie is set, but at the time the second view tries to read it, there is no cookie nor value for it...

# -*- coding: utf-8 -*-
from zope.publisher.browser import BrowserView
from DateTime import DateTime


class TestView(BrowserView):

    def __call__(self, *args, **kwargs):
        value = self.request.cookies.get('cookie-testing')
        if value is None:
            new_value = '34'
        else:
            new_value = int(value) + 3

        expires = (DateTime() + 2).toZone('GMT').rfc822()
        self.request.response.setCookie(
            'cookie-testing',
            new_value,
            path='/',
            expires=expires,
        )

        from plone import api
        self.request.response.redirect(api.portal.get().absolute_url() + '/@@test-view')
        return


class TestView2(BrowserView):

    def __call__(self, *args, **kwargs):
        value = self.request.cookies.get('cookie-testing')
        if value is None:
            value = 'None'

        return value

Register these two views with this ZCML:

  <browser:page
    for="*"
    name="cookie-redirect"
    permission="zope2.View"
    class=".test.TestView"
    />

  <browser:page
    for="*"
    name="test-view"
    permission="zope2.View"
    class=".test.TestView2"
    />

And you are good to go, call @@cookie-redirect and see that the output on the browser is None while the cookie is actually being set.

I tested that in external servers, so the problem seems to not be due to using localhost or the likes...

Any ideas? I'm totally puzzled... Is __call__ too early to check for cookies??

I ran into something like this when Varnish stripped my cookies.

1 Like

Spot on!! :tada:

For whatever reason, varnish does remove some cookies before sending the request to the backend server...

Seems that varnish, somehow, is clever enough to only keep the cookies that one wants to keep. I have this line

And as soon as I added my custom cookie name on it, the cookie made it to the server. :tada:

1 Like

All sorts of mechanisms set cookies, with Google Analytics being a prime example. Proxy caches like Varnish can be effectively poisoned by all these extra cookies -- nothing gets effectively cached when everything is unique.

You've found the spot in the Plone Ansible Playbook that sets up Varnish to strip most cookies. The idea is to strip everything that we don't care about before Varnish makes its final caching decisions. This kind of trick isn't new with the Ansible kit; it's just the latest iteration in several generations of tuning Varnish for Plone.

Your use case needed a new cookie to be respected. Adding that cookie to the cache_sanitize_cookie_exceptions list is exactly the right thing to do.

You might look at the cookie vmod of varnish.


Manipulating cookies as waaay easier with it:

sub vcl_recv {
        cookie.parse(req.http.cookie);
        cookie.filter_except("xyz,foo");
}
1 Like

Thanks, I will have a look!