From: Tim Starling Date: Wed, 20 Feb 2008 04:13:24 +0000 (+0000) Subject: Vary the cache on session, Token and LoggedOut cookies, but not UserID cookie. The... X-Git-Tag: 1.31.0-rc.0~49429 X-Git-Url: http://git.cyclocoop.org/%24image?a=commitdiff_plain;h=19c8fa643cc2f2392b7958f8d0f08347ea756d0b;p=lhc%2Fweb%2Fwiklou.git Vary the cache on session, Token and LoggedOut cookies, but not UserID cookie. The session and Token cookies are necessary because they can represent credentials. The UserID cookie is sometimes present after the credential cookies are expired and thus the request is anonymous. Need to vary on the LoggedOut cookie to prevent Squid from returning a 304 response for a logged-in page view cached on the client. Presumably this could be better dealt with with ETags. Always send Cache-Control: private when there is a cache-varying cookie present, to prevent pollution of the logged-in user cache with logged-out page views. This missing logic is why people have been reporting getting logged out. --- diff --git a/includes/OutputPage.php b/includes/OutputPage.php index 1fddeb7dd6..d29ba35ef4 100644 --- a/includes/OutputPage.php +++ b/includes/OutputPage.php @@ -519,22 +519,51 @@ class OutputPage { return wfSetVar( $this->mEnableClientCache, $state ); } - function uncacheableBecauseRequestvars() { + function getCacheVaryCookies() { + global $wgCookiePrefix; + return array( + "{$wgCookiePrefix}Token", + "{$wgCookiePrefix}LoggedOut", + session_name() ); + } + + function uncacheableBecauseRequestVars() { global $wgRequest; return $wgRequest->getText('useskin', false) === false && $wgRequest->getText('uselang', false) === false; } + /** + * Check if the request has a cache-varying cookie header + * If it does, it's very important that we don't allow public caching + */ + function haveCacheVaryCookies() { + global $wgRequest, $wgCookiePrefix; + $cookieHeader = $wgRequest->getHeader( 'cookie' ); + if ( $cookieHeader === false ) { + return false; + } + $cvCookies = $this->getCacheVaryCookies(); + foreach ( $cvCookies as $cookieName ) { + # Check for a simple string match, like the way squid does it + if ( strpos( $cookieHeader, $cookieName ) ) { + wfDebug( __METHOD__.": found $cookieName\n" ); + return true; + } + } + wfDebug( __METHOD__.": no cache-varying cookies found\n" ); + return false; + } + /** Get a complete X-Vary-Options header */ public function getXVO() { global $wgCookiePrefix; - return 'X-Vary-Options: ' . - # User ID cookie - "Cookie;string-contains={$wgCookiePrefix}UserID;" . - # Session cookie - 'string-contains=' . session_name() . ',' . - # Encoding checks for gzip only - 'Accept-Encoding;list-contains=gzip'; + $cvCookies = $this->getCacheVaryCookies(); + $xvo = 'X-Vary-Options: Accept-Encoding;list-contains=gzip,Cookie;'; + foreach ( $cvCookies as $cookieName ) { + $xvo .= 'string-contains=' . $cookieName; + } + return $xvo; } public function sendCacheControl() { @@ -552,9 +581,9 @@ class OutputPage { # Add an X-Vary-Options header for Squid with Wikimedia patches $response->header( $this->getXVO() ); - if( !$this->uncacheableBecauseRequestvars() && $this->mEnableClientCache ) { + if( !$this->uncacheableBecauseRequestVars() && $this->mEnableClientCache ) { if( $wgUseSquid && session_id() == '' && - ! $this->isPrintable() && $this->mSquidMaxage != 0 ) + ! $this->isPrintable() && $this->mSquidMaxage != 0 && !$this->haveCacheVaryCookies() ) { if ( $wgUseESI ) { # We'll purge the proxy cache explicitly, but require end user agents