private $mFollowPolicy = 'follow';
/**
- * @var array Headers that cause the cache to vary. Key is header name, value is an array of
- * options for the Key header.
+ * @var array Headers that cause the cache to vary. Key is header name,
+ * value should always be null. (Value was an array of options for
+ * the `Key` header, which was deprecated in 1.32 and removed in 1.34.)
*/
private $mVaryHeader = [
- 'Accept-Encoding' => [ 'match=gzip' ],
+ 'Accept-Encoding' => null,
];
/**
* Add an HTTP header that will influence on the cache
*
* @param string $header Header name
- * @param string[]|null $option Options for the Key header. See
- * https://datatracker.ietf.org/doc/draft-fielding-http-key/
- * for the list of valid options.
+ * @param string[]|null $option Deprecated; formerly options for the
+ * Key header, deprecated in 1.32 and removed in 1.34. See
+ * https://datatracker.ietf.org/doc/draft-fielding-http-key/
+ * for the list of formerly-valid options.
*/
public function addVaryHeader( $header, array $option = null ) {
- if ( !array_key_exists( $header, $this->mVaryHeader ) ) {
- $this->mVaryHeader[$header] = [];
+ if ( $option !== null && count( $option ) > 0 ) {
+ wfDeprecated( 'addVaryHeader $option is ignored', '1.34' );
}
- if ( !is_array( $option ) ) {
- $option = [];
+ if ( !array_key_exists( $header, $this->mVaryHeader ) ) {
+ $this->mVaryHeader[$header] = null;
}
- $this->mVaryHeader[$header] =
- array_unique( array_merge( $this->mVaryHeader[$header], $option ) );
}
/**
return 'Link: ' . implode( ',', $this->mLinkHeader );
}
- /**
- * Get a complete Key header
- *
- * @return string
- * @deprecated in 1.32; the IETF spec for this header expired w/o becoming
- * a standard.
- */
- public function getKeyHeader() {
- wfDeprecated( '$wgUseKeyHeader', '1.32' );
-
- $cvCookies = $this->getCacheVaryCookies();
-
- $cookiesOption = [];
- foreach ( $cvCookies as $cookieName ) {
- $cookiesOption[] = 'param=' . $cookieName;
- }
- $this->addVaryHeader( 'Cookie', $cookiesOption );
-
- foreach ( SessionManager::singleton()->getVaryHeaders() as $header => $options ) {
- $this->addVaryHeader( $header, $options );
- }
-
- $headers = [];
- foreach ( $this->mVaryHeader as $header => $option ) {
- $newheader = $header;
- if ( is_array( $option ) && count( $option ) > 0 ) {
- $newheader .= ';' . implode( ';', $option );
- }
- $headers[] = $newheader;
- }
- $key = 'Key: ' . implode( ',', $headers );
-
- return $key;
- }
-
/**
* T23672: Add Accept-Language to Vary and Key headers if there's no 'variant' parameter in GET.
*
$lang = $title->getPageLanguage();
if ( !$this->getRequest()->getCheck( 'variant' ) && $lang->hasVariants() ) {
- $variants = $lang->getVariants();
- $aloption = [];
- foreach ( $variants as $variant ) {
- if ( $variant === $lang->getCode() ) {
- continue;
- }
-
- // XXX Note that this code is not strictly correct: we
- // do a case-insensitive match in
- // LanguageConverter::getHeaderVariant() while the
- // (abandoned, draft) spec for the `Key` header only
- // allows case-sensitive matches. To match the logic
- // in LanguageConverter::getHeaderVariant() we should
- // also be looking at fallback variants and deprecated
- // mediawiki-internal codes, as well as BCP 47
- // normalized forms.
-
- $aloption[] = "substr=$variant";
-
- // IE and some other browsers use BCP 47 standards in their Accept-Language header,
- // like "zh-CN" or "zh-Hant". We should handle these too.
- $variantBCP47 = LanguageCode::bcp47( $variant );
- if ( $variantBCP47 !== $variant ) {
- $aloption[] = "substr=$variantBCP47";
- }
- }
- $this->addVaryHeader( 'Accept-Language', $aloption );
+ $this->addVaryHeader( 'Accept-Language' );
}
}
# maintain different caches for logged-in users and non-logged in ones
$response->header( $this->getVaryHeader() );
- if ( $config->get( 'UseKeyHeader' ) ) {
- $response->header( $this->getKeyHeader() );
- }
-
if ( $this->mEnableClientCache ) {
if (
$config->get( 'UseCdn' ) &&
*
* @covers OutputPage::addVaryHeader
* @covers OutputPage::getVaryHeader
- * @covers OutputPage::getKeyHeader
*
* @param array[] $calls For each array, call addVaryHeader() with those arguments
* @param string[] $cookies Array of cookie names to vary on
* @param string $vary Text of expected Vary header (including the 'Vary: ')
* @param string $key Text of expected Key header (including the 'Key: ')
*/
- public function testVaryHeaders( array $calls, array $cookies, $vary, $key ) {
+ public function testVaryHeaders( array $calls, array $cookies, $vary ) {
// Get rid of default Vary fields
$op = $this->getMockBuilder( OutputPage::class )
->setConstructorArgs( [ new RequestContext() ] )
->will( $this->returnValue( $cookies ) );
TestingAccessWrapper::newFromObject( $op )->mVaryHeader = [];
- $this->hideDeprecated( '$wgUseKeyHeader' );
+ $this->hideDeprecated( 'addVaryHeader $option is ignored' );
foreach ( $calls as $call ) {
$op->addVaryHeader( ...$call );
}
$this->assertEquals( $vary, $op->getVaryHeader(), 'Vary:' );
- $this->assertEquals( $key, $op->getKeyHeader(), 'Key:' );
}
public function provideVaryHeaders() {
- // note: getKeyHeader() automatically adds Vary: Cookie
return [
'No header' => [
[],
[],
'Vary: ',
- 'Key: Cookie',
],
'Single header' => [
[
],
[],
'Vary: Cookie',
- 'Key: Cookie',
],
'Non-unique headers' => [
[
],
[],
'Vary: Cookie, Accept-Language',
- 'Key: Cookie,Accept-Language',
],
'Two headers with single options' => [
+ // Options are deprecated since 1.34
[
[ 'Cookie', [ 'param=phpsessid' ] ],
[ 'Accept-Language', [ 'substr=en' ] ],
],
[],
'Vary: Cookie, Accept-Language',
- 'Key: Cookie;param=phpsessid,Accept-Language;substr=en',
],
'One header with multiple options' => [
+ // Options are deprecated since 1.34
[
[ 'Cookie', [ 'param=phpsessid', 'param=userId' ] ],
],
[],
'Vary: Cookie',
- 'Key: Cookie;param=phpsessid;param=userId',
],
'Duplicate option' => [
+ // Options are deprecated since 1.34
[
[ 'Cookie', [ 'param=phpsessid' ] ],
[ 'Cookie', [ 'param=phpsessid' ] ],
],
[],
'Vary: Cookie, Accept-Language',
- 'Key: Cookie;param=phpsessid,Accept-Language;substr=en',
],
'Same header, different options' => [
+ // Options are deprecated since 1.34
[
[ 'Cookie', [ 'param=phpsessid' ] ],
[ 'Cookie', [ 'param=userId' ] ],
],
[],
'Vary: Cookie',
- 'Key: Cookie;param=phpsessid;param=userId',
],
'No header, vary cookies' => [
[],
[ 'cookie1', 'cookie2' ],
'Vary: Cookie',
- 'Key: Cookie;param=cookie1;param=cookie2',
],
'Cookie header with option plus vary cookies' => [
+ // Options are deprecated since 1.34
[
[ 'Cookie', [ 'param=cookie1' ] ],
],
[ 'cookie2', 'cookie3' ],
'Vary: Cookie',
- 'Key: Cookie;param=cookie1;param=cookie2;param=cookie3',
],
'Non-cookie header plus vary cookies' => [
[
],
[ 'cookie' ],
'Vary: Accept-Language, Cookie',
- 'Key: Accept-Language,Cookie;param=cookie',
],
'Cookie and non-cookie headers plus vary cookies' => [
+ // Options are deprecated since 1.34
[
[ 'Cookie', [ 'param=cookie1' ] ],
[ 'Accept-Language' ],
],
[ 'cookie2' ],
'Vary: Cookie, Accept-Language',
- 'Key: Cookie;param=cookie1;param=cookie2,Accept-Language',
],
];
}
/**
* @dataProvider provideAddAcceptLanguage
* @covers OutputPage::addAcceptLanguage
- * @covers OutputPage::getKeyHeader
*/
public function testAddAcceptLanguage(
- $code, array $variants, array $expected, array $options = []
+ $code, array $variants, $expected, array $options = []
) {
$req = new FauxRequest( in_array( 'varianturl', $options ) ? [ 'variant' => 'x' ] : [] );
$op = $this->newInstance( [], $req, in_array( 'notitle', $options ) ? 'notitle' : null );
// This will run addAcceptLanguage()
$op->sendCacheControl();
-
- $this->hideDeprecated( '$wgUseKeyHeader' );
- $keyHeader = $op->getKeyHeader();
-
- if ( !$expected ) {
- $this->assertFalse( strpos( 'Accept-Language', $keyHeader ) );
- return;
- }
-
- $keyHeader = explode( ' ', $keyHeader, 2 )[1];
- $keyHeader = explode( ',', $keyHeader );
-
- $acceptLanguage = null;
- foreach ( $keyHeader as $item ) {
- if ( strpos( $item, 'Accept-Language;' ) === 0 ) {
- $acceptLanguage = $item;
- break;
- }
- }
-
- $expectedString = 'Accept-Language;substr=' . implode( ';substr=', $expected );
- $this->assertSame( $expectedString, $acceptLanguage );
+ $this->assertSame( "Vary: $expected", $op->getVaryHeader() );
}
public function provideAddAcceptLanguage() {
return [
- 'No variants' => [ 'en', [ 'en' ], [] ],
- 'One simple variant' => [ 'en', [ 'en', 'en-x-piglatin' ], [ 'en-x-piglatin' ] ],
+ 'No variants' => [
+ 'en',
+ [ 'en' ],
+ 'Accept-Encoding, Cookie',
+ ],
+ 'One simple variant' => [
+ 'en',
+ [ 'en', 'en-x-piglatin' ],
+ 'Accept-Encoding, Cookie, Accept-Language',
+ ],
'Multiple variants with BCP47 alternatives' => [
'zh',
[ 'zh', 'zh-hans', 'zh-cn', 'zh-tw' ],
- [ 'zh-hans', 'zh-Hans', 'zh-cn', 'zh-Hans-CN', 'zh-tw', 'zh-Hant-TW' ],
+ 'Accept-Encoding, Cookie, Accept-Language',
+ ],
+ 'No title' => [
+ 'en',
+ [ 'en', 'en-x-piglatin' ],
+ 'Accept-Encoding, Cookie',
+ [ 'notitle' ]
+ ],
+ 'Variant in URL' => [
+ 'en',
+ [ 'en', 'en-x-piglatin' ],
+ 'Accept-Encoding, Cookie',
+ [ 'varianturl' ]
],
- 'No title' => [ 'en', [ 'en', 'en-x-piglatin' ], [], [ 'notitle' ] ],
- 'Variant in URL' => [ 'en', [ 'en', 'en-x-piglatin' ], [], [ 'varianturl' ] ],
];
}