From b2dc451c822014ba4fcf9f5d71819b7bebe5af77 Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Fri, 23 Jul 2010 07:17:56 +0000 Subject: [PATCH] Rewrote r69339 etc. to clean up API cache header handling. * Introduced a "cache mode" concept to simplify the header generation code, and to avoid odd results when conflicting cache header requests are received from submodules, or at least to formalise the handling of such cases. * Made the cache mode private by default, so that code written in ignorance of caching tends to be safe. If different query modules are used in a single request, private caching is preferred over public caching. * Removed the "must-revalidate" option from all CC headers, this is really specific to page views with a hacked squid in front, I don't think it's applicable here. * Made the watchlist module private. This is really the definition of private data. There's nothing in the HTTP spec that says the URL for a CC:public request is private and can't be leaked. CC:private provides protection against unknown proxy behaviour. * In ApiQueryAllmessages: avoid calling $wgLang->getCode() to check if it's necessary to make a new $wgLang when lang= is specified, since this is the only thing that unstubs $wgUser. * Removed "FIXME: should this check $user instead of $wgUser?" Answer is no. --- includes/api/ApiBase.php | 2 - includes/api/ApiExpandTemplates.php | 3 + includes/api/ApiLogout.php | 1 - includes/api/ApiMain.php | 152 +++++++++++++++------ includes/api/ApiOpenSearch.php | 2 +- includes/api/ApiParse.php | 8 +- includes/api/ApiPatrol.php | 3 +- includes/api/ApiPurge.php | 1 - includes/api/ApiQuery.php | 57 ++++++-- includes/api/ApiQueryAllCategories.php | 6 +- includes/api/ApiQueryAllLinks.php | 6 +- includes/api/ApiQueryAllUsers.php | 6 +- includes/api/ApiQueryAllimages.php | 4 + includes/api/ApiQueryAllmessages.php | 18 ++- includes/api/ApiQueryAllpages.php | 4 + includes/api/ApiQueryBacklinks.php | 4 + includes/api/ApiQueryBase.php | 11 ++ includes/api/ApiQueryBlocks.php | 4 +- includes/api/ApiQueryCategories.php | 4 + includes/api/ApiQueryCategoryInfo.php | 6 +- includes/api/ApiQueryCategoryMembers.php | 4 + includes/api/ApiQueryDeletedrevs.php | 4 +- includes/api/ApiQueryDuplicateFiles.php | 4 + includes/api/ApiQueryExtLinksUsage.php | 6 +- includes/api/ApiQueryExternalLinks.php | 6 +- includes/api/ApiQueryFilearchive.php | 1 - includes/api/ApiQueryIWBacklinks.php | 4 + includes/api/ApiQueryIWLinks.php | 6 +- includes/api/ApiQueryImageInfo.php | 4 + includes/api/ApiQueryImages.php | 6 +- includes/api/ApiQueryInfo.php | 32 ++++- includes/api/ApiQueryLangLinks.php | 6 +- includes/api/ApiQueryLinks.php | 6 +- includes/api/ApiQueryLogEvents.php | 10 +- includes/api/ApiQueryProtectedTitles.php | 12 +- includes/api/ApiQueryRandom.php | 6 +- includes/api/ApiQueryRecentChanges.php | 23 +++- includes/api/ApiQueryRevisions.php | 15 +- includes/api/ApiQuerySearch.php | 4 + includes/api/ApiQuerySiteinfo.php | 4 + includes/api/ApiQueryTags.php | 4 + includes/api/ApiQueryUserContributions.php | 11 +- includes/api/ApiQueryUserInfo.php | 1 - includes/api/ApiQueryUsers.php | 11 +- includes/api/ApiQueryWatchlist.php | 5 +- includes/api/ApiWatch.php | 1 - 46 files changed, 381 insertions(+), 117 deletions(-) diff --git a/includes/api/ApiBase.php b/includes/api/ApiBase.php index 12d5de1085..3ce630a026 100644 --- a/includes/api/ApiBase.php +++ b/includes/api/ApiBase.php @@ -1105,8 +1105,6 @@ abstract class ApiBase { $this->dieUsage( 'Incorrect watchlist token provided -- please set a correct token in Special:Preferences', 'bad_wltoken' ); } } else { - // User not determined by URL, so don't cache - $this->getMain()->setVaryCookie(); if ( !$wgUser->isLoggedIn() ) { $this->dieUsage( 'You must be logged-in to have a watchlist', 'notloggedin' ); } diff --git a/includes/api/ApiExpandTemplates.php b/includes/api/ApiExpandTemplates.php index 033e77faa1..1c202271e0 100644 --- a/includes/api/ApiExpandTemplates.php +++ b/includes/api/ApiExpandTemplates.php @@ -42,6 +42,9 @@ class ApiExpandTemplates extends ApiBase { } public function execute() { + // Cache may vary on $wgUser because ParserOptions gets data from it + $this->getMain()->setCacheMode( 'anon-public-user-private' ); + // Get parameters $params = $this->extractRequestParams(); diff --git a/includes/api/ApiLogout.php b/includes/api/ApiLogout.php index 55adc3dd65..7307c0eb1b 100644 --- a/includes/api/ApiLogout.php +++ b/includes/api/ApiLogout.php @@ -42,7 +42,6 @@ class ApiLogout extends ApiBase { public function execute() { global $wgUser; - $this->getMain()->setCachePrivate(); $oldName = $wgUser->getName(); $wgUser->logout(); diff --git a/includes/api/ApiMain.php b/includes/api/ApiMain.php index 99a01b7d28..5a97fa9622 100644 --- a/includes/api/ApiMain.php +++ b/includes/api/ApiMain.php @@ -126,7 +126,8 @@ class ApiMain extends ApiBase { private $mResult, $mAction, $mShowVersions, $mEnableWrite, $mRequest; private $mInternalMode, $mSquidMaxage, $mModule, $mVaryCookie; - private $mCacheControl = array( 'must-revalidate' => true ); + private $mCacheMode = 'private'; + private $mCacheControl = array(); /** * Constructs an instance of ApiMain that utilizes the module and format specified by $request. @@ -216,19 +217,67 @@ class ApiMain extends ApiBase { 's-maxage' => $maxage ) ); } + + /** + * Set the type of caching headers which will be sent. + * + * @param $mode One of: + * - 'public': Cache this object in public caches, if the maxage or smaxage + * parameter is set, or if setCacheMaxAge() was called. If a maximum age is + * not provided by any of these means, the object will be private. + * - 'private': Cache this object only in private client-side caches. + * - 'anon-public-user-private': Make this object cacheable for logged-out + * users, but private for logged-in users. IMPORTANT: If this is set, it must be + * set consistently for a given URL, it cannot be set differently depending on + * things like the contents of the database, or whether the user is logged in. + * + * If the wiki does not allow anonymous users to read it, the mode set here + * will be ignored, and private caching headers will always be sent. In other words, + * the "public" mode is equivalent to saying that the data sent is as public as a page + * view. + * + * For user-dependent data, the private mode should generally be used. The + * anon-public-user-private mode should only be used where there is a particularly + * good performance reason for caching the anonymous response, but where the + * response to logged-in users may differ, or may contain private data. + * + * If this function is never called, then the default will be the private mode. + */ + public function setCacheMode( $mode ) { + if ( !in_array( $mode, array( 'private', 'public', 'anon-public-user-private' ) ) ) { + wfDebug( __METHOD__.": unrecognised cache mode \"$mode\"\n" ); + // Ignore for forwards-compatibility + return; + } + + if ( !in_array( 'read', User::getGroupPermissions( array( '*' ) ), true ) ) { + // Private wiki, only private headers + if ( $mode !== 'private' ) { + wfDebug( __METHOD__.": ignoring request for $mode cache mode, private wiki\n" ); + return; + } + } + + wfDebug( __METHOD__.": setting cache mode $mode\n" ); + $this->mCacheMode = $mode; + } /** - * Make sure Cache-Control: private is set. Use this when the output of a request - * is for the current recipient only and should not be cached in any shared cache. + * @deprecated Private caching is now the default, so there is usually no + * need to call this function. If there is a need, you can use + * $this->setCacheMode('private') */ public function setCachePrivate() { - $this->setCacheControl( array( 'private' => true ) ); + $this->setCacheMode( 'private' ); } /** * Set directives (key/value pairs) for the Cache-Control header. * Boolean values will be formatted as such, by including or omitting * without an equals sign. + * + * Cache control values set here will only be used if the cache mode is not + * private, see setCacheMode(). */ public function setCacheControl( $directives ) { $this->mCacheControl = $directives + $this->mCacheControl; @@ -241,26 +290,11 @@ class ApiMain extends ApiBase { * WARNING: This function must be called CONSISTENTLY for a given URL. This means that a * given URL must either always or never call this function; if it sometimes does and * sometimes doesn't, stuff will break. + * + * @deprecated Use setCacheMode( 'anon-public-user-private' ) */ public function setVaryCookie() { - $this->mVaryCookie = true; - } - - /** - * Actually output the Vary: Cookie header and its friends, if flagged with setVaryCookie(). - * Outputs the appropriate X-Vary-Options header and Cache-Control: private if needed. - */ - private function outputVaryCookieHeader() { - global $wgUseXVO, $wgOut; - if ( $this->mVaryCookie ) { - header( 'Vary: Cookie' ); - if ( $wgUseXVO ) { - header( $wgOut->getXVO() ); - if ( $wgOut->haveCacheVaryCookies() ) { - $this->setCacheControl( array( 'private' => true ) ); - } - } - } + $this->setCacheMode( 'anon-public-user-private' ); } /** @@ -313,8 +347,7 @@ class ApiMain extends ApiBase { $errCode = $this->substituteResultWithError( $e ); // Error results should not be cached - $this->setCacheMaxAge( 0 ); - $this->setCachePrivate(); + $this->setCacheMode( 'private' ); $headerStr = 'MediaWiki-API-Error: ' . $errCode; if ( $e->getCode() === 0 ) { @@ -330,10 +363,47 @@ class ApiMain extends ApiBase { $this->mPrinter->safeProfileOut(); $this->printResult( true ); } - - // If this wiki is private, don't cache anything ever - if ( ! in_array( 'read', User::getGroupPermissions( array( '*' ) ), true ) ) { - $this->setCachePrivate(); + + // Send cache headers after any code which might generate an error, to + // avoid sending public cache headers for errors. + $this->sendCacheHeaders(); + + if ( $this->mPrinter->getIsHtml() && !$this->mPrinter->isDisabled() ) { + echo wfReportTime(); + } + + ob_end_flush(); + } + + protected function sendCacheHeaders() { + if ( $this->mCacheMode == 'private' ) { + header( 'Cache-Control: private' ); + return; + } + + if ( $this->mCacheMode == 'anon-public-user-private' ) { + global $wgUseXVO, $wgOut; + header( 'Vary: Accept-Encoding, Cookie' ); + if ( $wgUseXVO ) { + header( $wgOut->getXVO() ); + if ( $wgOut->haveCacheVaryCookies() ) { + // Logged in, mark this request private + header( 'Cache-Control: private' ); + return; + } + // Logged out, send normal public headers below + } elseif ( session_id() != '' ) { + // Logged in or otherwise has session (e.g. anonymous users who have edited) + // Mark request private + header( 'Cache-Control: private' ); + return; + } // else no XVO and anonymous, send public headers below + } else /* if public */ { + // Give a debugging message if the user object is unstubbed on a public request + global $wgUser; + if ( !( $wgUser instanceof StubUser ) ) { + wfDebug( __METHOD__." \$wgUser is unstubbed on a public request!\n" ); + } } // If nobody called setCacheMaxAge(), use the (s)maxage parameters @@ -344,11 +414,20 @@ class ApiMain extends ApiBase { $this->mCacheControl['max-age'] = $this->getParameter( 'maxage' ); } - // Set the cache expiration at the last moment, as any errors may change the expiration. - // if $this->mSquidMaxage == 0, the expiry time is set to the first second of unix epoch - $exp = min( $this->mCacheControl['s-maxage'], $this->mCacheControl['max-age'] ); - $expires = ( $exp == 0 ? 1 : time() + $exp ); - header( 'Expires: ' . wfTimestamp( TS_RFC2822, $expires ) ); + if ( !$this->mCacheControl['s-maxage'] && !$this->mCacheControl['max-age'] ) { + // Public cache not requested + // Sending a Vary header in this case is harmless, and protects us + // against conditional calls of setCacheMaxAge(). + header( 'Cache-Control: private' ); + return; + } + + $this->mCacheControl['public'] = true; + + // Send an Expires header + $maxAge = min( $this->mCacheControl['s-maxage'], $this->mCacheControl['max-age'] ); + $expiryUnixTime = ( $maxAge == 0 ? 1 : time() + $maxAge ); + header( 'Expires: ' . wfTimestamp( TS_RFC2822, $expiryUnixTime ) ); // Construct the Cache-Control header $ccHeader = ''; @@ -366,13 +445,6 @@ class ApiMain extends ApiBase { } header( "Cache-Control: $ccHeader" ); - $this->outputVaryCookieHeader(); - - if ( $this->mPrinter->getIsHtml() && !$this->mPrinter->isDisabled() ) { - echo wfReportTime(); - } - - ob_end_flush(); } /** diff --git a/includes/api/ApiOpenSearch.php b/includes/api/ApiOpenSearch.php index d8dc2513ce..022ecd11e2 100644 --- a/includes/api/ApiOpenSearch.php +++ b/includes/api/ApiOpenSearch.php @@ -56,7 +56,7 @@ class ApiOpenSearch extends ApiBase { // Open search results may be stored for a very long // time $this->getMain()->setCacheMaxAge( $wgSearchSuggestCacheExpiry ); - $this->getMain()->setCacheControl( array( 'must-revalidate' => false ) ); + $this->getMain()->setCacheMode( 'public' ); $srchres = PrefixSearch::titleSearch( $search, $limit, $namespaces ); diff --git a/includes/api/ApiParse.php b/includes/api/ApiParse.php index ae419a8d42..b7b2563613 100644 --- a/includes/api/ApiParse.php +++ b/includes/api/ApiParse.php @@ -38,6 +38,9 @@ class ApiParse extends ApiBase { } public function execute() { + // The data is hot but user-dependent, like page views, so we set vary cookies + $this->getMain()->setCacheMode( 'anon-public-user-private' ); + // Get parameters $params = $this->extractRequestParams(); $text = $params['text']; @@ -161,7 +164,6 @@ class ApiParse extends ApiBase { if ( $params['pst'] || $params['onlypst'] ) { $text = $wgParser->preSaveTransform( $text, $titleObj, $wgUser, $popts ); - $this->getMain()->setVaryCookie(); } if ( $params['onlypst'] ) { // Build a result and bail out @@ -187,7 +189,6 @@ class ApiParse extends ApiBase { if ( !is_null( $params['summary'] ) ) { $result_array['parsedsummary'] = array(); - $this->getMain()->setVaryCookie(); $result->setContent( $result_array['parsedsummary'], $wgUser->getSkin()->formatComment( $params['summary'], $titleObj ) ); } @@ -222,7 +223,6 @@ class ApiParse extends ApiBase { if ( isset( $prop['headitems'] ) || isset( $prop['headhtml'] ) ) { $out = new OutputPage; $out->addParserOutputNoText( $p_result ); - $this->getMain()->setVaryCookie(); $userSkin = $wgUser->getSkin(); } @@ -468,4 +468,4 @@ class ApiParse extends ApiBase { public function getVersion() { return __CLASS__ . ': $Id$'; } -} \ No newline at end of file +} diff --git a/includes/api/ApiPatrol.php b/includes/api/ApiPatrol.php index 361fe408d7..2f248aff10 100644 --- a/includes/api/ApiPatrol.php +++ b/includes/api/ApiPatrol.php @@ -41,7 +41,6 @@ class ApiPatrol extends ApiBase { * Patrols the article or provides the reason the patrol failed. */ public function execute() { - $this->getMain()->setCachePrivate(); $params = $this->extractRequestParams(); if ( !isset( $params['rcid'] ) ) { @@ -107,4 +106,4 @@ class ApiPatrol extends ApiBase { public function getVersion() { return __CLASS__ . ': $Id$'; } -} \ No newline at end of file +} diff --git a/includes/api/ApiPurge.php b/includes/api/ApiPurge.php index 4936a60752..aee27e7a8e 100644 --- a/includes/api/ApiPurge.php +++ b/includes/api/ApiPurge.php @@ -42,7 +42,6 @@ class ApiPurge extends ApiBase { */ public function execute() { global $wgUser; - $this->getMain()->setCachePrivate(); $params = $this->extractRequestParams(); if ( !$wgUser->isAllowed( 'purge' ) ) { $this->dieUsageMsg( array( 'cantpurge' ) ); diff --git a/includes/api/ApiQuery.php b/includes/api/ApiQuery.php index 063b478f99..b3caa1009d 100644 --- a/includes/api/ApiQuery.php +++ b/includes/api/ApiQuery.php @@ -232,9 +232,15 @@ class ApiQuery extends ApiBase { $this->instantiateModules( $modules, 'list', $this->mQueryListModules ); $this->instantiateModules( $modules, 'meta', $this->mQueryMetaModules ); + $cacheMode = 'public'; + // If given, execute generator to substitute user supplied data with generated data. if ( isset( $this->params['generator'] ) ) { - $this->executeGeneratorModule( $this->params['generator'], $modules ); + $generator = $this->newGenerator( $this->params['generator'] ); + $params = $generator->extractRequestParams(); + $cacheMode = $this->mergeCacheMode( $cacheMode, + $generator->getCacheMode( $params ) ); + $this->executeGeneratorModule( $generator, $modules ); } else { // Append custom fields and populate page/revision information $this->addCustomFldsToPageSet( $modules, $this->mPageSet ); @@ -246,11 +252,35 @@ class ApiQuery extends ApiBase { // Execute all requested modules. foreach ( $modules as $module ) { + $params = $module->extractRequestParams(); + $cacheMode = $this->mergeCacheMode( + $cacheMode, $module->getCacheMode( $params ) ); $module->profileIn(); $module->execute(); wfRunHooks( 'APIQueryAfterExecute', array( &$module ) ); $module->profileOut(); } + + // Set the cache mode + $this->getMain()->setCacheMode( $cacheMode ); + } + + /** + * Update a cache mode string, applying the cache mode of a new module to it. + * The cache mode may increase in the level of privacy, but public modules + * added to private data do not decrease the level of privacy. + */ + protected function mergeCacheMode( $cacheMode, $modCacheMode ) { + if ( $modCacheMode === 'anon-public-user-private' ) { + if ( $cacheMode !== 'private' ) { + $cacheMode = 'anon-public-user-private'; + } + } elseif ( $modCacheMode === 'public' ) { + // do nothing, if it's public already it will stay public + } else { // private + $cacheMode = 'private'; + } + return $cacheMode; } /** @@ -458,12 +488,9 @@ class ApiQuery extends ApiBase { } /** - * For generator mode, execute generator, and use its output as new - * ApiPageSet - * @param $generatorName string Module name - * @param $modules array of module objects + * Create a generator object of the given type and return it */ - protected function executeGeneratorModule( $generatorName, $modules ) { + public function newGenerator( $generatorName ) { // Find class that implements requested generator if ( isset( $this->mQueryListModules[$generatorName] ) ) { $className = $this->mQueryListModules[$generatorName]; @@ -472,17 +499,23 @@ class ApiQuery extends ApiBase { } else { ApiBase::dieDebug( __METHOD__, "Unknown generator=$generatorName" ); } - - // Generator results - $resultPageSet = new ApiPageSet( $this, $this->redirects, $this->convertTitles ); - - // Create and execute the generator $generator = new $className ( $this, $generatorName ); if ( !$generator instanceof ApiQueryGeneratorBase ) { $this->dieUsage( "Module $generatorName cannot be used as a generator", 'badgenerator' ); } - $generator->setGeneratorMode(); + return $generator; + } + + /** + * For generator mode, execute generator, and use its output as new + * ApiPageSet + * @param $generatorName string Module name + * @param $modules array of module objects + */ + protected function executeGeneratorModule( $generator, $modules ) { + // Generator results + $resultPageSet = new ApiPageSet( $this, $this->redirects, $this->convertTitles ); // Add any additional fields modules may need $generator->requestExtraData( $this->mPageSet ); diff --git a/includes/api/ApiQueryAllCategories.php b/includes/api/ApiQueryAllCategories.php index 1a57676b23..afdc52da5e 100644 --- a/includes/api/ApiQueryAllCategories.php +++ b/includes/api/ApiQueryAllCategories.php @@ -44,6 +44,10 @@ class ApiQueryAllCategories extends ApiQueryGeneratorBase { $this->run(); } + public function getCacheMode( $params ) { + return 'public'; + } + public function executeGenerator( $resultPageSet ) { $this->run( $resultPageSet ); } @@ -179,4 +183,4 @@ class ApiQueryAllCategories extends ApiQueryGeneratorBase { public function getVersion() { return __CLASS__ . ': $Id$'; } -} \ No newline at end of file +} diff --git a/includes/api/ApiQueryAllLinks.php b/includes/api/ApiQueryAllLinks.php index 340aea37df..40c63f81cb 100644 --- a/includes/api/ApiQueryAllLinks.php +++ b/includes/api/ApiQueryAllLinks.php @@ -43,6 +43,10 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase { $this->run(); } + public function getCacheMode( $params ) { + return 'public'; + } + public function executeGenerator( $resultPageSet ) { $this->run( $resultPageSet ); } @@ -221,4 +225,4 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase { public function getVersion() { return __CLASS__ . ': $Id$'; } -} \ No newline at end of file +} diff --git a/includes/api/ApiQueryAllUsers.php b/includes/api/ApiQueryAllUsers.php index 9354745291..1f4d858a7f 100644 --- a/includes/api/ApiQueryAllUsers.php +++ b/includes/api/ApiQueryAllUsers.php @@ -184,6 +184,10 @@ class ApiQueryAllUsers extends ApiQueryBase { $result->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), 'u' ); } + public function getCacheMode( $params ) { + return 'public'; + } + public function getAllowedParams() { return array( 'from' => null, @@ -241,4 +245,4 @@ class ApiQueryAllUsers extends ApiQueryBase { public function getVersion() { return __CLASS__ . ': $Id$'; } -} \ No newline at end of file +} diff --git a/includes/api/ApiQueryAllimages.php b/includes/api/ApiQueryAllimages.php index 3a5c427862..a63edecc2c 100644 --- a/includes/api/ApiQueryAllimages.php +++ b/includes/api/ApiQueryAllimages.php @@ -55,6 +55,10 @@ class ApiQueryAllimages extends ApiQueryGeneratorBase { $this->run(); } + public function getCacheMode( $params ) { + return 'public'; + } + public function executeGenerator( $resultPageSet ) { if ( $resultPageSet->isResolvingRedirects() ) { $this->dieUsage( 'Use "gaifilterredir=nonredirects" option instead of "redirects" when using allimages as a generator', 'params' ); diff --git a/includes/api/ApiQueryAllmessages.php b/includes/api/ApiQueryAllmessages.php index 6e5cbd2903..86e2f91554 100644 --- a/includes/api/ApiQueryAllmessages.php +++ b/includes/api/ApiQueryAllmessages.php @@ -45,12 +45,9 @@ class ApiQueryAllmessages extends ApiQueryBase { global $wgLang; $oldLang = null; - if ( !is_null( $params['lang'] ) && $params['lang'] != $wgLang->getCode() ) { + if ( !is_null( $params['lang'] ) ) { $oldLang = $wgLang; // Keep $wgLang for restore later $wgLang = Language::factory( $params['lang'] ); - } else if ( is_null( $params['lang'] ) ) { - // Language not determined by URL but by user preferences, so don't cache - $this->getMain()->setVaryCookie(); } $prop = array_flip( (array)$params['prop'] ); @@ -131,6 +128,19 @@ class ApiQueryAllmessages extends ApiQueryBase { } } + public function getCacheMode( $params ) { + if ( is_null( $params['lang'] ) ) { + // Language not specified, will be fetched from preferences + return 'anon-public-user-private'; + } elseif ( $params['enableparser'] ) { + // User-specific parser options will be used + return 'anon-public-user-private'; + } else { + // OK to cache + return 'public'; + } + } + public function getAllowedParams() { return array( 'messages' => array( diff --git a/includes/api/ApiQueryAllpages.php b/includes/api/ApiQueryAllpages.php index 3c3c949e56..571264ae39 100644 --- a/includes/api/ApiQueryAllpages.php +++ b/includes/api/ApiQueryAllpages.php @@ -43,6 +43,10 @@ class ApiQueryAllpages extends ApiQueryGeneratorBase { $this->run(); } + public function getCacheMode( $params ) { + return 'public'; + } + public function executeGenerator( $resultPageSet ) { if ( $resultPageSet->isResolvingRedirects() ) { $this->dieUsage( 'Use "gapfilterredir=nonredirects" option instead of "redirects" when using allpages as a generator', 'params' ); diff --git a/includes/api/ApiQueryBacklinks.php b/includes/api/ApiQueryBacklinks.php index aed143af84..1ab0c67a29 100644 --- a/includes/api/ApiQueryBacklinks.php +++ b/includes/api/ApiQueryBacklinks.php @@ -92,6 +92,10 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase { $this->run(); } + public function getCacheMode( $params ) { + return 'public'; + } + public function executeGenerator( $resultPageSet ) { $this->run( $resultPageSet ); } diff --git a/includes/api/ApiQueryBase.php b/includes/api/ApiQueryBase.php index 61a107253d..80b2ca9414 100644 --- a/includes/api/ApiQueryBase.php +++ b/includes/api/ApiQueryBase.php @@ -46,6 +46,17 @@ abstract class ApiQueryBase extends ApiBase { $this->resetQueryParams(); } + /** + * Get the cache mode for the data generated by this module. Override this + * in the module subclass. + * + * Public caching will only be allowed if *all* the modules that supply + * data for a given request return a cache mode of public. + */ + public function getCacheMode( $params ) { + return 'private'; + } + /** * Blank the internal arrays with query parameters */ diff --git a/includes/api/ApiQueryBlocks.php b/includes/api/ApiQueryBlocks.php index 2db17bd87c..dd0e53f03e 100644 --- a/includes/api/ApiQueryBlocks.php +++ b/includes/api/ApiQueryBlocks.php @@ -125,8 +125,6 @@ class ApiQueryBlocks extends ApiQueryBase { ) ); } - // Make sure private data (deleted blocks) isn't cached - $this->getMain()->setVaryCookie(); if ( !$wgUser->isAllowed( 'hideuser' ) ) { $this->addWhereFld( 'ipb_deleted', 0 ); } @@ -308,4 +306,4 @@ class ApiQueryBlocks extends ApiQueryBase { public function getVersion() { return __CLASS__ . ': $Id$'; } -} \ No newline at end of file +} diff --git a/includes/api/ApiQueryCategories.php b/includes/api/ApiQueryCategories.php index 0d6c15fc88..9d95fc7200 100644 --- a/includes/api/ApiQueryCategories.php +++ b/includes/api/ApiQueryCategories.php @@ -43,6 +43,10 @@ class ApiQueryCategories extends ApiQueryGeneratorBase { $this->run(); } + public function getCacheMode( $params ) { + return 'public'; + } + public function executeGenerator( $resultPageSet ) { $this->run( $resultPageSet ); } diff --git a/includes/api/ApiQueryCategoryInfo.php b/includes/api/ApiQueryCategoryInfo.php index a89a0e1a08..09306b4aad 100644 --- a/includes/api/ApiQueryCategoryInfo.php +++ b/includes/api/ApiQueryCategoryInfo.php @@ -94,6 +94,10 @@ class ApiQueryCategoryInfo extends ApiQueryBase { } } + public function getCacheMode( $params ) { + return 'public'; + } + public function getAllowedParams() { return array( 'continue' => null, @@ -117,4 +121,4 @@ class ApiQueryCategoryInfo extends ApiQueryBase { public function getVersion() { return __CLASS__ . ': $Id$'; } -} \ No newline at end of file +} diff --git a/includes/api/ApiQueryCategoryMembers.php b/includes/api/ApiQueryCategoryMembers.php index 5eb65f1cbd..d0919d0278 100644 --- a/includes/api/ApiQueryCategoryMembers.php +++ b/includes/api/ApiQueryCategoryMembers.php @@ -43,6 +43,10 @@ class ApiQueryCategoryMembers extends ApiQueryGeneratorBase { $this->run(); } + public function getCacheMode( $params ) { + return 'public'; + } + public function executeGenerator( $resultPageSet ) { $this->run( $resultPageSet ); } diff --git a/includes/api/ApiQueryDeletedrevs.php b/includes/api/ApiQueryDeletedrevs.php index 598584444c..e5635daf8b 100644 --- a/includes/api/ApiQueryDeletedrevs.php +++ b/includes/api/ApiQueryDeletedrevs.php @@ -41,7 +41,6 @@ class ApiQueryDeletedrevs extends ApiQueryBase { public function execute() { global $wgUser; - $this->getMain()->setVaryCookie(); // Before doing anything at all, let's check permissions if ( !$wgUser->isAllowed( 'deletedhistory' ) ) { $this->dieUsage( 'You don\'t have permission to view deleted revision information', 'permissiondenied' ); @@ -210,7 +209,6 @@ class ApiQueryDeletedrevs extends ApiQueryBase { if ( $fld_parsedcomment ) { global $wgUser; - $this->getMain()->setVaryCookie(); $rev['parsedcomment'] = $wgUser->getSkin()->formatComment( $row->ar_comment, $title ); } if ( $fld_minor && $row->ar_minor_edit == 1 ) { @@ -367,4 +365,4 @@ class ApiQueryDeletedrevs extends ApiQueryBase { public function getVersion() { return __CLASS__ . ': $Id$'; } -} \ No newline at end of file +} diff --git a/includes/api/ApiQueryDuplicateFiles.php b/includes/api/ApiQueryDuplicateFiles.php index cdc63d7bd4..72d17bb2fa 100644 --- a/includes/api/ApiQueryDuplicateFiles.php +++ b/includes/api/ApiQueryDuplicateFiles.php @@ -43,6 +43,10 @@ class ApiQueryDuplicateFiles extends ApiQueryGeneratorBase { $this->run(); } + public function getCacheMode( $params ) { + return 'public'; + } + public function executeGenerator( $resultPageSet ) { $this->run( $resultPageSet ); } diff --git a/includes/api/ApiQueryExtLinksUsage.php b/includes/api/ApiQueryExtLinksUsage.php index 31e7bc738a..f92ef41208 100644 --- a/includes/api/ApiQueryExtLinksUsage.php +++ b/includes/api/ApiQueryExtLinksUsage.php @@ -41,6 +41,10 @@ class ApiQueryExtLinksUsage extends ApiQueryGeneratorBase { $this->run(); } + public function getCacheMode( $params ) { + return 'public'; + } + public function executeGenerator( $resultPageSet ) { $this->run( $resultPageSet ); } @@ -226,4 +230,4 @@ class ApiQueryExtLinksUsage extends ApiQueryGeneratorBase { public function getVersion() { return __CLASS__ . ': $Id$'; } -} \ No newline at end of file +} diff --git a/includes/api/ApiQueryExternalLinks.php b/includes/api/ApiQueryExternalLinks.php index a679c47149..082b340e97 100644 --- a/includes/api/ApiQueryExternalLinks.php +++ b/includes/api/ApiQueryExternalLinks.php @@ -83,6 +83,10 @@ class ApiQueryExternalLinks extends ApiQueryBase { } } + public function getCacheMode( $params ) { + return 'public'; + } + public function getAllowedParams() { return array( 'limit' => array( @@ -117,4 +121,4 @@ class ApiQueryExternalLinks extends ApiQueryBase { public function getVersion() { return __CLASS__ . ': $Id$'; } -} \ No newline at end of file +} diff --git a/includes/api/ApiQueryFilearchive.php b/includes/api/ApiQueryFilearchive.php index 38ca3d977d..e7393451f1 100644 --- a/includes/api/ApiQueryFilearchive.php +++ b/includes/api/ApiQueryFilearchive.php @@ -43,7 +43,6 @@ class ApiQueryFilearchive extends ApiQueryBase { public function execute() { global $wgUser; - $this->getMain()->setVaryCookie(); // Before doing anything at all, let's check permissions if ( !$wgUser->isAllowed( 'deletedhistory' ) ) { $this->dieUsage( 'You don\'t have permission to view deleted file information', 'permissiondenied' ); diff --git a/includes/api/ApiQueryIWBacklinks.php b/includes/api/ApiQueryIWBacklinks.php index 35baa48ef3..ab5cbaef1d 100644 --- a/includes/api/ApiQueryIWBacklinks.php +++ b/includes/api/ApiQueryIWBacklinks.php @@ -147,6 +147,10 @@ class ApiQueryIWBacklinks extends ApiQueryGeneratorBase { } } + public function getCacheMode( $params ) { + return 'public'; + } + public function getAllowedParams() { return array( 'prefix' => null, diff --git a/includes/api/ApiQueryIWLinks.php b/includes/api/ApiQueryIWLinks.php index 03288a9beb..90eb751189 100644 --- a/includes/api/ApiQueryIWLinks.php +++ b/includes/api/ApiQueryIWLinks.php @@ -108,6 +108,10 @@ class ApiQueryIWLinks extends ApiQueryBase { } } + public function getCacheMode( $params ) { + return 'public'; + } + public function getAllowedParams() { return array( 'url' => null, @@ -150,4 +154,4 @@ class ApiQueryIWLinks extends ApiQueryBase { public function getVersion() { return __CLASS__ . ': $Id$'; } -} \ No newline at end of file +} diff --git a/includes/api/ApiQueryImageInfo.php b/includes/api/ApiQueryImageInfo.php index 17cb2facbd..465d8c0472 100644 --- a/includes/api/ApiQueryImageInfo.php +++ b/includes/api/ApiQueryImageInfo.php @@ -274,6 +274,10 @@ class ApiQueryImageInfo extends ApiQueryBase { return $retval; } + public function getCacheMode( $params ) { + return 'public'; + } + private function getContinueStr( $img ) { return $img->getOriginalTitle()->getText() . '|' . $img->getTimestamp(); diff --git a/includes/api/ApiQueryImages.php b/includes/api/ApiQueryImages.php index b961d882ec..790c45f3e3 100644 --- a/includes/api/ApiQueryImages.php +++ b/includes/api/ApiQueryImages.php @@ -121,6 +121,10 @@ class ApiQueryImages extends ApiQueryGeneratorBase { } } + public function getCacheMode( $params ) { + return 'public'; + } + public function getAllowedParams() { return array( 'limit' => array( @@ -163,4 +167,4 @@ class ApiQueryImages extends ApiQueryGeneratorBase { public function getVersion() { return __CLASS__ . ': $Id$'; } -} \ No newline at end of file +} diff --git a/includes/api/ApiQueryInfo.php b/includes/api/ApiQueryInfo.php index 896e200bb9..4dfeb7f60a 100644 --- a/includes/api/ApiQueryInfo.php +++ b/includes/api/ApiQueryInfo.php @@ -253,7 +253,6 @@ class ApiQueryInfo extends ApiQueryBase { } if ( $this->fld_watched ) { - $this->getMain()->setVaryCookie(); $this->getWatchedInfo(); } @@ -304,9 +303,6 @@ class ApiQueryInfo extends ApiQueryBase { } if ( !is_null( $this->params['token'] ) ) { - // Don't cache tokens - $this->getMain()->setCachePrivate(); - $tokenFunctions = $this->getTokenFunctions(); $pageInfo['starttimestamp'] = wfTimestamp( TS_ISO_8601, time() ); foreach ( $this->params['token'] as $t ) { @@ -607,6 +603,28 @@ class ApiQueryInfo extends ApiQueryBase { } } + public function getCacheMode( $params ) { + $publicProps = array( + 'protection', + 'talkid', + 'subjectid', + 'url', + 'preload', + 'displaytitle', + ); + if ( !is_null( $params['prop'] ) ) { + foreach ( $params['prop'] as $prop ) { + if ( !in_array( $prop, $publicProps ) ) { + return 'private'; + } + } + } + if ( !is_null( $params['token'] ) ) { + return 'private'; + } + return 'public'; + } + public function getAllowedParams() { return array( 'prop' => array( @@ -615,12 +633,14 @@ class ApiQueryInfo extends ApiQueryBase { ApiBase::PARAM_TYPE => array( 'protection', 'talkid', - 'watched', + 'watched', # private 'subjectid', 'url', - 'readable', + 'readable', # private 'preload', 'displaytitle', + // If you add more properties here, please consider whether they + // need to be added to getCacheMode() ) ), 'token' => array( ApiBase::PARAM_DFLT => null, diff --git a/includes/api/ApiQueryLangLinks.php b/includes/api/ApiQueryLangLinks.php index 5e36bcac1a..761e448a1d 100644 --- a/includes/api/ApiQueryLangLinks.php +++ b/includes/api/ApiQueryLangLinks.php @@ -95,6 +95,10 @@ class ApiQueryLangLinks extends ApiQueryBase { } } + public function getCacheMode( $params ) { + return 'public'; + } + public function getAllowedParams() { return array( 'limit' => array( @@ -135,4 +139,4 @@ class ApiQueryLangLinks extends ApiQueryBase { public function getVersion() { return __CLASS__ . ': $Id$'; } -} \ No newline at end of file +} diff --git a/includes/api/ApiQueryLinks.php b/includes/api/ApiQueryLinks.php index 9e5b75dde9..732f31064e 100644 --- a/includes/api/ApiQueryLinks.php +++ b/includes/api/ApiQueryLinks.php @@ -65,6 +65,10 @@ class ApiQueryLinks extends ApiQueryGeneratorBase { $this->run(); } + public function getCacheMode( $params ) { + return 'public'; + } + public function executeGenerator( $resultPageSet ) { $this->run( $resultPageSet ); } @@ -232,4 +236,4 @@ class ApiQueryLinks extends ApiQueryGeneratorBase { public function getVersion() { return __CLASS__ . ': $Id$'; } -} \ No newline at end of file +} diff --git a/includes/api/ApiQueryLogEvents.php b/includes/api/ApiQueryLogEvents.php index 51ca8b655f..e56b895895 100644 --- a/includes/api/ApiQueryLogEvents.php +++ b/includes/api/ApiQueryLogEvents.php @@ -282,7 +282,6 @@ class ApiQueryLogEvents extends ApiQueryBase { if ( $this->fld_parsedcomment ) { global $wgUser; - $this->getMain()->setVaryCookie(); $vals['parsedcomment'] = $wgUser->getSkin()->formatComment( $row->log_comment, $title ); } } @@ -301,6 +300,15 @@ class ApiQueryLogEvents extends ApiQueryBase { return $vals; } + public function getCacheMode( $params ) { + if ( !is_null( $params['prop'] ) && in_array( 'parsedcomment', $params['prop'] ) ) { + // formatComment() calls wfMsg() among other things + return 'anon-public-user-private'; + } else { + return 'public'; + } + } + public function getAllowedParams() { global $wgLogTypes, $wgLogActions; return array( diff --git a/includes/api/ApiQueryProtectedTitles.php b/includes/api/ApiQueryProtectedTitles.php index 19b8182b56..e0b7616df7 100644 --- a/includes/api/ApiQueryProtectedTitles.php +++ b/includes/api/ApiQueryProtectedTitles.php @@ -101,7 +101,6 @@ class ApiQueryProtectedTitles extends ApiQueryGeneratorBase { if ( isset( $prop['parsedcomment'] ) ) { global $wgUser; - $this->getMain()->setVaryCookie(); $vals['parsedcomment'] = $wgUser->getSkin()->formatComment( $row->pt_reason, $title ); } @@ -131,6 +130,15 @@ class ApiQueryProtectedTitles extends ApiQueryGeneratorBase { } } + public function getCacheMode( $params ) { + if ( !is_null( $params['prop'] ) && in_array( 'parsedcomment', $params['prop'] ) ) { + // formatComment() calls wfMsg() among other things + return 'anon-public-user-private'; + } else { + return 'public'; + } + } + public function getAllowedParams() { global $wgRestrictionLevels; return array( @@ -210,4 +218,4 @@ class ApiQueryProtectedTitles extends ApiQueryGeneratorBase { public function getVersion() { return __CLASS__ . ': $Id$'; } -} \ No newline at end of file +} diff --git a/includes/api/ApiQueryRandom.php b/includes/api/ApiQueryRandom.php index 41aef1a022..4ffaeac76f 100644 --- a/includes/api/ApiQueryRandom.php +++ b/includes/api/ApiQueryRandom.php @@ -119,6 +119,10 @@ if ( !defined( 'MEDIAWIKI' ) ) { return $vals; } + public function getCacheMode( $params ) { + return 'public'; + } + public function getAllowedParams() { return array( 'namespace' => array( @@ -160,4 +164,4 @@ if ( !defined( 'MEDIAWIKI' ) ) { public function getVersion() { return __CLASS__ . ': $Id: ApiQueryRandom.php overlordq$'; } -} \ No newline at end of file +} diff --git a/includes/api/ApiQueryRecentChanges.php b/includes/api/ApiQueryRecentChanges.php index b0d7e837fd..609e86df98 100644 --- a/includes/api/ApiQueryRecentChanges.php +++ b/includes/api/ApiQueryRecentChanges.php @@ -143,7 +143,6 @@ class ApiQueryRecentChanges extends ApiQueryBase { // Check permissions global $wgUser; if ( isset( $show['patrolled'] ) || isset( $show['!patrolled'] ) ) { - $this->getMain()->setVaryCookie(); if ( !$wgUser->useRCPatrol() && !$wgUser->useNPPatrol() ) { $this->dieUsage( 'You need the patrol right to request the patrolled flag', 'permissiondenied' ); } @@ -376,7 +375,6 @@ class ApiQueryRecentChanges extends ApiQueryBase { if ( $this->fld_parsedcomment && isset( $row->rc_comment ) ) { global $wgUser; - $this->getMain()->setVaryCookie(); $vals['parsedcomment'] = $wgUser->getSkin()->formatComment( $row->rc_comment, $title ); } @@ -413,9 +411,6 @@ class ApiQueryRecentChanges extends ApiQueryBase { } if ( !is_null( $this->token ) ) { - // Don't cache tokens - $this->getMain()->setCachePrivate(); - $tokenFunctions = $this->getTokenFunctions(); foreach ( $this->token as $t ) { $val = call_user_func( $tokenFunctions[$t], $row->rc_cur_id, @@ -449,6 +444,24 @@ class ApiQueryRecentChanges extends ApiQueryBase { } } + public function getCacheMode( $params ) { + if ( isset( $params['show'] ) ) { + foreach ( $params['show'] as $show ) { + if ( $show === 'patrolled' || $show === '!patrolled' ) { + return 'private'; + } + } + } + if ( isset( $params['token'] ) ) { + return 'private'; + } + if ( !is_null( $params['prop'] ) && in_array( 'parsedcomment', $params['prop'] ) ) { + // formatComment() calls wfMsg() among other things + return 'anon-public-user-private'; + } + return 'public'; + } + public function getAllowedParams() { return array( 'start' => array( diff --git a/includes/api/ApiQueryRevisions.php b/includes/api/ApiQueryRevisions.php index 1a79e7e534..3130405320 100644 --- a/includes/api/ApiQueryRevisions.php +++ b/includes/api/ApiQueryRevisions.php @@ -394,7 +394,6 @@ class ApiQueryRevisions extends ApiQueryBase { if ( $this->fld_parsedcomment ) { global $wgUser; - $this->getMain()->setVaryCookie(); $vals['parsedcomment'] = $wgUser->getSkin()->formatComment( $comment, $title ); } } @@ -411,9 +410,6 @@ class ApiQueryRevisions extends ApiQueryBase { } if ( !is_null( $this->token ) ) { - // Don't cache tokens - $this->getMain()->setCachePrivate(); - $tokenFunctions = $this->getTokenFunctions(); foreach ( $this->token as $t ) { $val = call_user_func( $tokenFunctions[$t], $title->getArticleID(), $title, $revision ); @@ -487,6 +483,17 @@ class ApiQueryRevisions extends ApiQueryBase { return $vals; } + public function getCacheMode( $params ) { + if ( isset( $params['token'] ) ) { + return 'private'; + } + if ( !is_null( $params['prop'] ) && in_array( 'parsedcomment', $params['prop'] ) ) { + // formatComment() calls wfMsg() among other things + return 'anon-public-user-private'; + } + return 'public'; + } + public function getAllowedParams() { return array( 'prop' => array( diff --git a/includes/api/ApiQuerySearch.php b/includes/api/ApiQuerySearch.php index 86ba895893..2527307657 100644 --- a/includes/api/ApiQuerySearch.php +++ b/includes/api/ApiQuerySearch.php @@ -164,6 +164,10 @@ class ApiQuerySearch extends ApiQueryGeneratorBase { } } + public function getCacheMode( $params ) { + return 'public'; + } + public function getAllowedParams() { return array( 'search' => null, diff --git a/includes/api/ApiQuerySiteinfo.php b/includes/api/ApiQuerySiteinfo.php index 0bfd3c3a52..2ffb700b17 100644 --- a/includes/api/ApiQuerySiteinfo.php +++ b/includes/api/ApiQuerySiteinfo.php @@ -427,6 +427,10 @@ class ApiQuerySiteinfo extends ApiQueryBase { return $this->getResult()->addValue( 'query', $property, $data ); } + public function getCacheMode( $params ) { + return 'public'; + } + public function getAllowedParams() { return array( 'prop' => array( diff --git a/includes/api/ApiQueryTags.php b/includes/api/ApiQueryTags.php index ad708bd44c..6c5c9a429b 100644 --- a/includes/api/ApiQueryTags.php +++ b/includes/api/ApiQueryTags.php @@ -129,6 +129,10 @@ class ApiQueryTags extends ApiQueryBase { return true; } + public function getCacheMode( $params ) { + return 'public'; + } + public function getAllowedParams() { return array( 'continue' => array( diff --git a/includes/api/ApiQueryUserContributions.php b/includes/api/ApiQueryUserContributions.php index c6eadb22bc..c62b4239b7 100644 --- a/includes/api/ApiQueryUserContributions.php +++ b/includes/api/ApiQueryUserContributions.php @@ -163,8 +163,6 @@ class ApiQueryContributions extends ApiQueryBase { ); } - // Make sure private data (deleted revisions) isn't cached - $this->getMain()->setVaryCookie(); if ( !$wgUser->isAllowed( 'hideuser' ) ) { $this->addWhere( $this->getDB()->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0' ); } @@ -216,8 +214,6 @@ class ApiQueryContributions extends ApiQueryBase { $this->fld_patrolled ) { global $wgUser; - // Don't cache private data - $this->getMain()->setVaryCookie(); if ( !$wgUser->useRCPatrol() && !$wgUser->useNPPatrol() ) { $this->dieUsage( 'You need the patrol right to request the patrolled flag', 'permissiondenied' ); } @@ -320,7 +316,6 @@ class ApiQueryContributions extends ApiQueryBase { if ( $this->fld_parsedcomment ) { global $wgUser; - $this->getMain()->setVaryCookie(); $vals['parsedcomment'] = $wgUser->getSkin()->formatComment( $row->rev_comment, $title ); } } @@ -352,6 +347,12 @@ class ApiQueryContributions extends ApiQueryBase { wfTimestamp( TS_ISO_8601, $row->rev_timestamp ); } + public function getCacheMode( $params ) { + // This module provides access to deleted revisions and patrol flags if + // the requester is logged in + return 'anon-public-user-private'; + } + public function getAllowedParams() { return array( 'limit' => array( diff --git a/includes/api/ApiQueryUserInfo.php b/includes/api/ApiQueryUserInfo.php index 8599314323..ffe1a0cf3d 100644 --- a/includes/api/ApiQueryUserInfo.php +++ b/includes/api/ApiQueryUserInfo.php @@ -40,7 +40,6 @@ class ApiQueryUserInfo extends ApiQueryBase { } public function execute() { - $this->getMain()->setCachePrivate(); $params = $this->extractRequestParams(); $result = $this->getResult(); $r = array(); diff --git a/includes/api/ApiQueryUsers.php b/includes/api/ApiQueryUsers.php index b50fe71906..23ea58dd0e 100644 --- a/includes/api/ApiQueryUsers.php +++ b/includes/api/ApiQueryUsers.php @@ -160,9 +160,6 @@ if ( !defined( 'MEDIAWIKI' ) ) { } if ( !is_null( $params['token'] ) ) { - // Don't cache tokens - $this->getMain()->setCachePrivate(); - $tokenFunctions = $this->getTokenFunctions(); foreach ( $params['token'] as $t ) { $val = call_user_func( $tokenFunctions[$t], $user ); @@ -235,6 +232,14 @@ if ( !defined( 'MEDIAWIKI' ) ) { return array_merge( $groups, Autopromote::getAutopromoteGroups( $user ) ); } + public function getCacheMode( $params ) { + if ( isset( $params['token'] ) ) { + return 'private'; + } else { + return 'public'; + } + } + public function getAllowedParams() { return array( 'prop' => array( diff --git a/includes/api/ApiQueryWatchlist.php b/includes/api/ApiQueryWatchlist.php index 9339ac01cd..2d61f82027 100644 --- a/includes/api/ApiQueryWatchlist.php +++ b/includes/api/ApiQueryWatchlist.php @@ -74,7 +74,6 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase { $this->fld_notificationtimestamp = isset( $prop['notificationtimestamp'] ); if ( $this->fld_patrol ) { - $this->getMain()->setVaryCookie(); if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) { $this->dieUsage( 'patrol property is not available', 'patrol' ); } @@ -141,9 +140,8 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase { $this->dieUsageMsg( array( 'show' ) ); } - // Check permissions. FIXME: should this check $user instead of $wgUser? + // Check permissions. if ( isset( $show['patrolled'] ) || isset( $show['!patrolled'] ) ) { - $this->getMain()->setVaryCookie(); if ( !$wgUser->useRCPatrol() && !$wgUser->useNPPatrol() ) { $this->dieUsage( 'You need the patrol right to request the patrolled flag', 'permissiondenied' ); } @@ -272,7 +270,6 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase { if ( $this->fld_parsedcomment && isset( $row->rc_comment ) ) { global $wgUser; - $this->getMain()->setVaryCookie(); $vals['parsedcomment'] = $wgUser->getSkin()->formatComment( $row->rc_comment, $title ); } diff --git a/includes/api/ApiWatch.php b/includes/api/ApiWatch.php index 6ef86917ee..f0532f995d 100644 --- a/includes/api/ApiWatch.php +++ b/includes/api/ApiWatch.php @@ -41,7 +41,6 @@ class ApiWatch extends ApiBase { public function execute() { global $wgUser; - $this->getMain()->setCachePrivate(); if ( !$wgUser->isLoggedIn() ) { $this->dieUsage( 'You must be logged-in to have a watchlist', 'notloggedin' ); } -- 2.20.1