Index: includes/OutputPage.php =================================================================== --- includes/OutputPage.php (revision 59487) +++ includes/OutputPage.php (working copy) @@ -50,6 +50,7 @@ private $mIndexPolicy = 'index'; private $mFollowPolicy = 'follow'; + private $mVaryHeader = array(); /** * Constructor @@ -807,20 +808,45 @@ /** Get a complete X-Vary-Options header */ public function getXVO() { + $this->addVaryHeader( 'Accept-Encoding', 'list-contains', 'gzip' ); + $this->addVaryHeader( 'Cookie' ); $cvCookies = $this->getCacheVaryCookies(); - $xvo = 'X-Vary-Options: Accept-Encoding;list-contains=gzip,Cookie;'; + foreach ( $cvCookies as $cookieName ) { + $this->addVaryHeader( 'Cookie', 'string-contains', $cookieName ); + } + $xvo = 'X-Vary-Options: '; $first = true; - foreach ( $cvCookies as $cookieName ) { + foreach ( $this->mVaryHeader as $header => $options ) { if ( $first ) { $first = false; } else { - $xvo .= ';'; + $xvo .= ', '; } - $xvo .= 'string-contains=' . $cookieName; + $xvo .= $header; + foreach ( $options as $option => $values ) { + foreach ( $values as $value ) { + $xvo .= '; ' . $option . '=' . $value; + } + } } return $xvo; } + public function addVaryHeader( $header, $option = false, $value = false ) { + $header = strtolower( $header ); + if ( !array_key_exists( $header, $this->mVaryHeader ) ) { + $this->mVaryHeader[$header] = array(); + } + if ( $option ) { + if ( !array_key_exists( $option, $this->mVaryHeader[$header] ) ) { + $this->mVaryHeader[$header][$option] = array(); + } + if ( !in_array( $value, $this->mVaryHeader[$header][$option] ) ) { + $this->mVaryHeader[$header][$option][] = $value; + } + } + } + public function sendCacheControl() { global $wgUseSquid, $wgUseESI, $wgUseETag, $wgSquidMaxage, $wgRequest, $wgUseXVO; @@ -828,15 +854,16 @@ if ($wgUseETag && $this->mETag) $response->header("ETag: $this->mETag"); - # don't serve compressed data to clients who can't handle it - # maintain different caches for logged-in users and non-logged in ones - $response->header( 'Vary: Accept-Encoding, Cookie' ); - if ( $wgUseXVO ) { # Add an X-Vary-Options header for Squid with Wikimedia patches $response->header( $this->getXVO() ); } + # don't serve compressed data to clients who can't handle it + # maintain different caches for logged-in users and non-logged in ones + # $this->mVaryHeader is not filled until getXVO is called + $response->header( 'Vary: ' . join( ', ', array_keys( $this->mVaryHeader ) ) ); + if( !$this->uncacheableBecauseRequestVars() && $this->mEnableClientCache ) { if( $wgUseSquid && session_id() == '' && ! $this->isPrintable() && $this->mSquidMaxage != 0 && !$this->haveCacheVaryCookies() ) Index: languages/LanguageConverter.php =================================================================== --- languages/LanguageConverter.php (revision 59487) +++ languages/LanguageConverter.php (working copy) @@ -130,7 +130,7 @@ * @public */ function getPreferredVariant( $fromUser = true ) { - global $wgUser, $wgRequest, $wgVariantArticlePath, $wgDefaultLanguageVariant; + global $wgUser, $wgRequest, $wgVariantArticlePath, $wgDefaultLanguageVariant, $wgOut; if($this->mPreferredVariant) return $this->mPreferredVariant; @@ -185,6 +185,11 @@ // variable in case this is called before the user's // preference is loaded if( array_key_exists( 'HTTP_ACCEPT_LANGUAGE', $_SERVER ) ) { + + foreach ( $this->mVariants as $variant ) { + $wgOut->addVaryHeader( 'Accept-Language', 'string-contains', $variant ); + } + $acceptLanguage = strtolower( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ); // explode by comma