Search code examples
djangocookiesmiddleware

How to check for cookie support in a middleware that uses sessions in Django?


I got a middleware that create a user account automatically for each new user and redirect:

class LogNewUser(object):

    def process_request(self, request):

        user_id = request.session.get('uid', None)

        if not user_id:
            user = User.objects.create(username=generate_name())
            request.session['uid'] = user.pk
            return redirect(request.path)

        else:
            request.user = User.objects.get(pk=user_id)

Of course, if the browser has cookie disable, this creates an infinite redirection loop.

I'd like to test if user has cookie enable, and if yes, do my thing, and if not, create a specific user object which will be the same for all non cookie users.

I tried different combinations of request.session.set_test_cookie() and request.session.test_cookie_worked() but I can't find a way do to what I want.


Solution

  • I realized that the challenge was to find a way to say you already tried to set a test cookie. Since HTTP is stateless, the only way to do that is to enclose the information into a URL we redirect to and catch it back again in the middleware:

    class LogNewUser(object):
    
        def process_request(self, request):
    
            if 'testcookie' in request.path:
    
                next = request.GET.get('next', '/')
    
                if not request.session.test_cookie_worked():
                    return render(request, 'cookie_error.html')
    
                request.session.delete_test_cookie()
    
                user = User.objects.create(username=generate_name())
                request.session['uid'] = user.pk
                return redirect(request.GET.get('next', '/'))
    
            if not request.user.is_authenticated():
    
                user_id = request.session.get('uid', None)
    
                if not user_id:
    
                    request.session.set_test_cookie()
                    return redirect('/testcookie/?next=%s' % request.path)
    
                request.user = User.objects.get(pk=uid)
    

    In this code, we don't have the ability to create a User object for all non-cookie users. It's because it's just not possible with this technique without having a redirection at each request, which would kill POST requests. But:

    • I here handle this case with a redirection for non-cookie users to a template that explains the problem and a way to turn on cookies for their browser.
    • You can by pass this issue by using session ID in the URL query string if you really need to.