views:

703

answers:

3

Hi all,

I made a custom handler404 for a authenticated Django website to avoid information leakage.

def check_logged_in_404(request):
    """ Custom 404. Show friendly 404 when logged in and redirect to /login
    when not logged in.
    """
    if request.user.is_authenticated():
        return render_to_response('404.html')
    else:
        return HttpResponseRedirect('/login')

Functionally it does exactly what I want. However the 404 return page has a status 200, which is correct code-wise. But this obviously needs to be a 404 return status.

A raise404 doesn't work because, if not ending in a infinite recursion, it comes back here and thus results in the same issue.

I tried a HttpResponseNotFound, but this only takes a string as a argument and not a template, which is not to DRY-ish.

And I manually tried to set the header with:

    response = render_to_response('404.html')
    response['Status'] = "Not Found - 404"
    return response

Then the status header is indeed set but the browser still shows up a 200.

I'm out of options .. Anybody that has tips, please be my hero ... :)

Thanx and regards,

Gerard.

Edit: I tried the status field value in all sort btw, but no luck :(

+7  A: 

I'd use render_to_string and HttpResponseNotFound, e.g. return HttpResponseNotFound(render_to_string('404.html')).

PiotrLegnica
Hmm didn't realise about "render_to_string". Still curious about why the set status codes are not honoured.Anyway ... you definitely earned the "somebody's hero" badge .. ;) .. thanx a lot!
GerardJP
+5  A: 

I finally found why the returned status code didnt work. Instead of setting a header message, it simply is:

response.status_code = 404

Nevertheless, the code suggested by PiotrLegnica definitely wins on simplicity, readability and beauty .. The badge still stands ;)

Regards,

Gerard.

GerardJP
+1  A: 

Why don't you just use Http404 exception?

if request.user.is_authenticated():
    raise Http404
else:
    return HttpResponseRedirect('/login')

That should be just fine for you.

gruszczy
Somehow I endup with a 500 response when raising the Http404. Nevertheless, I think there needs to be a distinction within the function otherwise I end up with a recursion error, or I need to write a page_not_found() view. Thanx anyway.
GerardJP
Have you imported Http404 from django.http?
gruszczy
Emphh, when you raise it you get redirected to your 404 handler. Some people want them to be custom.
DataGreed