Commit c161bf21 authored by Luke Plant's avatar Luke Plant
Browse files

Fixed #6552, #12031 - Make django.core.context_processors.auth lazy to avoid "Vary: Cookie"

Thanks to olau@iola.dk, Suor for the report



git-svn-id: http://code.djangoproject.com/svn/django/trunk@11623 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent f14833ee
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@ from datetime import datetime

from django.conf import settings
from django.contrib.auth.backends import RemoteUserBackend
from django.contrib.auth.models import AnonymousUser, User
from django.contrib.auth.models import User
from django.test import TestCase


@@ -30,15 +30,15 @@ class RemoteUserTest(TestCase):
        num_users = User.objects.count()

        response = self.client.get('/remote_user/')
        self.assert_(isinstance(response.context['user'], AnonymousUser))
        self.assert_(response.context['user'].is_anonymous())
        self.assertEqual(User.objects.count(), num_users)

        response = self.client.get('/remote_user/', REMOTE_USER=None)
        self.assert_(isinstance(response.context['user'], AnonymousUser))
        self.assert_(response.context['user'].is_anonymous())
        self.assertEqual(User.objects.count(), num_users)

        response = self.client.get('/remote_user/', REMOTE_USER='')
        self.assert_(isinstance(response.context['user'], AnonymousUser))
        self.assert_(response.context['user'].is_anonymous())
        self.assertEqual(User.objects.count(), num_users)

    def test_unknown_user(self):
@@ -115,7 +115,7 @@ class RemoteUserNoCreateTest(RemoteUserTest):
    def test_unknown_user(self):
        num_users = User.objects.count()
        response = self.client.get('/remote_user/', REMOTE_USER='newuser')
        self.assert_(isinstance(response.context['user'], AnonymousUser))
        self.assert_(response.context['user'].is_anonymous())
        self.assertEqual(User.objects.count(), num_users)


+41 −9
Original line number Diff line number Diff line
@@ -8,6 +8,27 @@ RequestContext.
"""

from django.conf import settings
from django.utils.functional import lazy, memoize, LazyObject

class ContextLazyObject(LazyObject):
    """
    A lazy object initialised from any function, useful for lazily
    adding things to the Context.

    Designed for compound objects of unknown type. For simple objects of known
    type, use django.utils.functional.lazy.
    """
    def __init__(self, func):
        """
        Pass in a callable that returns the actual value to be used
        """
        self.__dict__['_setupfunc'] = func
        # For some reason, we have to inline LazyObject.__init__ here to avoid
        # recursion
        self._wrapped = None

    def _setup(self):
        self._wrapped = self._setupfunc()

def auth(request):
    """
@@ -17,15 +38,26 @@ def auth(request):
    If there is no 'user' attribute in the request, uses AnonymousUser (from
    django.contrib.auth).
    """
    # If we access request.user, request.session is accessed, which results in
    # 'Vary: Cookie' being sent in every request that uses this context
    # processor, which can easily be every request on a site if
    # TEMPLATE_CONTEXT_PROCESSORS has this context processor added.  This kills
    # the ability to cache.  So, we carefully ensure these attributes are lazy.
    # We don't use django.utils.functional.lazy() for User, because that
    # requires knowing the class of the object we want to proxy, which could
    # break with custom auth backends.  LazyObject is a less complete but more
    # flexible solution that is a good enough wrapper for 'User'.
    def get_user():
        if hasattr(request, 'user'):
        user = request.user
            return request.user
        else:
            from django.contrib.auth.models import AnonymousUser
        user = AnonymousUser()
            return AnonymousUser()

    return {
        'user': user,
        'messages': user.get_and_delete_messages(),
        'perms': PermWrapper(user),
        'user': ContextLazyObject(get_user),
        'messages': lazy(memoize(lambda: get_user().get_and_delete_messages(), {}, 0), list)(),
        'perms':  lazy(lambda: PermWrapper(get_user()), PermWrapper)(),
    }

def debug(request):
+17 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<django-objects version="1.0">
    <object pk="100" model="auth.user">
        <field type="CharField" name="username">super</field>
        <field type="CharField" name="first_name">Super</field>
        <field type="CharField" name="last_name">User</field>
        <field type="CharField" name="email">super@example.com</field>
        <field type="CharField" name="password">sha1$995a3$6011485ea3834267d719b4c801409b8b1ddd0158</field>
        <field type="BooleanField" name="is_staff">True</field>
        <field type="BooleanField" name="is_active">True</field>
        <field type="BooleanField" name="is_superuser">True</field>
        <field type="DateTimeField" name="last_login">2007-05-30 13:20:10</field>
        <field type="DateTimeField" name="date_joined">2007-05-30 13:20:10</field>
        <field to="auth.group" name="groups" rel="ManyToManyRel"></field>
        <field to="auth.permission" name="user_permissions" rel="ManyToManyRel"></field>
    </object>
</django-objects>
+1 −0
Original line number Diff line number Diff line
{{ user }}
+1 −0
Original line number Diff line number Diff line
{% for m in messages %}{{ m }}{% endfor %}
Loading