2013-09-23 4 views
4

Я использую лак в качестве кеша переднего конца для приложения Django. Все это хорошо работает в отношении конфигурации VCL. Проблема заключается в том, что после выхода пользователя из системы csrftoken cookie не удаляется, и с этого момента на лаке есть ответ MISS вместо HIT. После прочтения здесь на StackOverflow некоторые смежные вопросы у меня есть этот вид режимом ВЫХОД ИЗ СИСТЕМЫDjango не может удалить csrftoken после выхода из системы

def logout_view(request): 
    response = render_to_response('registration/logout.html', {}, context_instance=RequestContext(request)) 

    if request.user.is_authenticated(): 
     logout(request) 

     if request.GET.get('next', False): 
      response = HttpResponseRedirect(next) 

    response.delete_cookie('sessionid') 
    response.delete_cookie('csrftoken') 
    return response 

и этот ответ заголовки после того, как пользователь нажал странице выхода

Response Headers 
Age:0 
Cache-Control:max-age=600 
Connection:keep-alive 
Content-Language:en 
Content-Type:text/html; charset=utf-8 
Date:Mon, 23 Sep 2013 09:20:43 GMT 
Expires:Mon, 23 Sep 2013 09:30:43 GMT 
P3P:CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT" 
Server:nginx/1.4.1 
Set-Cookie:sessionid=; expires=Thu, 01-Jan-1970 00:00:00 GMT; Max-Age=0; Path=/ 
Set-Cookie:csrftoken=; expires=Thu, 01-Jan-1970 00:00:00 GMT; Max-Age=0; Path=/ 
Transfer-Encoding:chunked 
Vary:Cookie, Accept-Language, Host 
Via:1.1 varnish 
X-Cache:MISS 
X-Varnish:1950616479 

default.vcl для полноты:

backend default { 
    .host = "127.0.0.1"; 
    .port = "8000"; 
} 

sub vcl_recv { 
    set req.grace = 15s; 

    if (req.http.Cookie) { 
     set req.http.Cookie = regsuball(req.http.Cookie, "(^|;) *__utm.=[^;]+;? *", "\1"); # removes all cookies named __utm? (utma, utmb...) - tracking thing 
    } 

    # unless sessionid/csrftoken is in the request, don't pass ANY cookies (referral_source, utm, etc) 
    if (req.request == "GET" && (req.url ~ "^/static" || (req.http.cookie !~ "flash_sessionid" && req.http.cookie !~ "csrftoken"))) { 
     remove req.http.Cookie; 
    } 

    # normalize accept-encoding to account for different browsers 
    # see: https://www.varnish-cache.org/trac/wiki/VCLExampleNormalizeAcceptEncoding 
    if (req.http.Accept-Encoding) { 
     if (req.http.Accept-Encoding ~ "gzip") { 
      set req.http.Accept-Encoding = "gzip"; 
     } elsif (req.http.Accept-Encoding ~ "deflate") { 
      set req.http.Accept-Encoding = "deflate"; 
     } else { 
      # unknown algorithm 
      remove req.http.Accept-Encoding; 
     } 
    } 
} 

sub vcl_fetch { 
    set beresp.ttl = 300s; 
    set beresp.grace = 15s; 

    # static files always cached 
    if (req.url ~ "^/static") { 
     unset beresp.http.set-cookie; 
     return (deliver); 
    } 

    # pass through for anything with a session/csrftoken set 
    if (beresp.http.set-cookie ~ "flash_sessionid" || beresp.http.set-cookie ~ "csrftoken") { 
     return (hit_for_pass); 
    } else { 
     return (deliver); 
    } 
} 

sub vcl_deliver { 
    # Add a header to indicate a cache HIT/MISS 
    if (obj.hits > 0) { 
     set resp.http.X-Cache = "HIT"; 
    } else { 
     set resp.http.X-Cache = "MISS"; 
    } 
    return (deliver); 
} 

В заголовках ответов я вижу, что Django задает значение cookie для даты в прошлом, однако csrftoken cookie s до следующего запроса.

Я также попытался удалить промежуточное программное обеспечение 'django.middleware.csrf.CsrfViewMiddleware', но файл cookie все еще существует.

ответ

1

Вы можете решить эту проблему путем редактирования vcl_fetch следующим образом:

sub vcl_fetch { 
    # pass through for anything with a session/csrftoken set 
    if (beresp.http.set-cookie ~ "flash_sessionid" || beresp.http.set-cookie ~ "csrftoken" || beresp.http.set-cookie ~ "sessionid") { 
     return (hit_for_pass); 
    } else { 
     return (deliver); 
    } 
} 

Таким образом, вы проверяете для Set-Cookie:sessionid, а также.

Varnish видит только первый заголовок Set-Cookie при использовании beresp.http.set-cookie, поэтому в вашем случае Varnish возвращает vcl_deliver вместо hit_for_pass.

Для дальнейшего чтения я хотел бы взглянуть на vmod_header.

Смежные вопросы