From: Yuri Astrakhan Date: Sun, 22 Oct 2006 23:45:20 +0000 (+0000) Subject: API * cache expiration control X-Git-Tag: 1.31.0-rc.0~55394 X-Git-Url: http://git.cyclocoop.org/fichier?a=commitdiff_plain;h=eb02c1a87b46faa7fce5f01a6cb290b8a78f4ae4;p=lhc%2Fweb%2Fwiklou.git API * cache expiration control * Added PHP-serialized & WDDX formats --- diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index 388512861f..b1525c546b 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -242,6 +242,8 @@ function __autoload($className) { 'ApiFormatBase' => 'includes/api/ApiFormatBase.php', 'Services_JSON' => 'includes/api/ApiFormatJson_json.php', 'ApiFormatJson' => 'includes/api/ApiFormatJson.php', + 'ApiFormatPhp' => 'includes/api/ApiFormatPhp.php', + 'ApiFormatWddx' => 'includes/api/ApiFormatWddx.php', 'ApiFormatXml' => 'includes/api/ApiFormatXml.php', 'Spyc' => 'includes/api/ApiFormatYaml_spyc.php', 'ApiFormatYaml' => 'includes/api/ApiFormatYaml.php', diff --git a/includes/api/ApiFormatBase.php b/includes/api/ApiFormatBase.php index 013c075294..1a415eb8e2 100644 --- a/includes/api/ApiFormatBase.php +++ b/includes/api/ApiFormatBase.php @@ -82,7 +82,6 @@ abstract class ApiFormatBase extends ApiBase { return; // skip any initialization header("Content-Type: $mime; charset=utf-8;"); - header("Cache-Control: private, s-maxage=0, max-age=0"); if ($isHtml) { ?> diff --git a/includes/api/ApiFormatPhp.php b/includes/api/ApiFormatPhp.php new file mode 100644 index 0000000000..0b0a820fc7 --- /dev/null +++ b/includes/api/ApiFormatPhp.php @@ -0,0 +1,54 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * http://www.gnu.org/copyleft/gpl.html + */ + +if (!defined('MEDIAWIKI')) { + // Eclipse helper - will be ignored in production + require_once ('ApiFormatBase.php'); +} + +class ApiFormatPhp extends ApiFormatBase { + + public function __construct($main, $format) { + parent :: __construct($main, $format); + } + + public function getMimeType() { + return 'application/vnd.php.serialized'; + } + + public function execute() { + $this->printText(serialize($this->getResultData())); + } + + protected function getDescription() { + return 'Output data in serialized PHP format'; + } + + public function getVersion() { + return __CLASS__ . ': $Id$'; + } +} +?> \ No newline at end of file diff --git a/includes/api/ApiFormatWddx.php b/includes/api/ApiFormatWddx.php new file mode 100644 index 0000000000..a075626412 --- /dev/null +++ b/includes/api/ApiFormatWddx.php @@ -0,0 +1,89 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * http://www.gnu.org/copyleft/gpl.html + */ + +if (!defined('MEDIAWIKI')) { + // Eclipse helper - will be ignored in production + require_once ('ApiFormatBase.php'); +} + +class ApiFormatWddx extends ApiFormatBase { + + public function __construct($main, $format) { + parent :: __construct($main, $format); + } + + public function getMimeType() { + return 'text/xml'; + } + + public function execute() { + if (function_exists('wddx_serialize_value')) { + $this->printText(wddx_serialize_value($this->getResultData())); + } else { + $this->printText(''); + $this->printText('
'); + $this->slowWddxPrinter($this->getResultData()); + $this->printText(''); + } + } + + /** + * Recursivelly go through the object and output its data in WDDX format. + */ + function slowWddxPrinter($elemValue) { + switch (gettype($elemValue)) { + case 'array' : + $this->printText(''); + foreach ($elemValue as $subElemName => $subElemValue) { + $this->printText(wfElement('var', array ( + 'name' => $subElemName + ), null)); + $this->slowWddxPrinter($subElemValue); + $this->printText(''); + } + $this->printText(''); + break; + case 'integer' : + case 'double' : + $this->printText(wfElement('number', null, $elemValue)); + break; + case 'string' : + $this->printText(wfElement('string', null, $elemValue)); + break; + default : + ApiBase :: dieDebug(__METHOD__, 'Unknown type ' . gettype($elemValue)); + } + } + + protected function getDescription() { + return 'Output data in WDDX format'; + } + + public function getVersion() { + return __CLASS__ . ': $Id$'; + } +} +?> \ No newline at end of file diff --git a/includes/api/ApiMain.php b/includes/api/ApiMain.php index 078b0ad713..12ad3314ba 100644 --- a/includes/api/ApiMain.php +++ b/includes/api/ApiMain.php @@ -29,7 +29,6 @@ if (!defined('MEDIAWIKI')) { require_once ('ApiBase.php'); } - /** * This is the main API class, used for both external and internal processing. */ @@ -57,16 +56,20 @@ class ApiMain extends ApiBase { private static $Formats = array ( 'json' => 'ApiFormatJson', 'jsonfm' => 'ApiFormatJson', - 'raw' => 'ApiFormatJson', - 'rawfm' => 'ApiFormatJson', + 'php' => 'ApiFormatPhp', + 'phpfm' => 'ApiFormatPhp', + 'wddx' => 'ApiFormatWddx', + 'wddxfm' => 'ApiFormatWddx', 'xml' => 'ApiFormatXml', 'xmlfm' => 'ApiFormatXml', 'yaml' => 'ApiFormatYaml', - 'yamlfm' => 'ApiFormatYaml' + 'yamlfm' => 'ApiFormatYaml', + 'raw' => 'ApiFormatJson', + 'rawfm' => 'ApiFormatJson' ); private $mPrinter, $mModules, $mModuleNames, $mFormats, $mFormatNames; - private $mResult, $mShowVersions, $mEnableWrite, $mRequest, $mInternalMode; + private $mResult, $mShowVersions, $mEnableWrite, $mRequest, $mInternalMode, $mSquidMaxage; /** * Constructor @@ -77,18 +80,20 @@ class ApiMain extends ApiBase { // Special handling for the main module: $parent === $this parent :: __construct($this, 'main'); - $this->mModules =& self::$Modules; - $this->mModuleNames = array_keys($this->mModules); // todo: optimize - $this->mFormats =& self::$Formats; - $this->mFormatNames = array_keys($this->mFormats); // todo: optimize - + $this->mModules = & self :: $Modules; + $this->mModuleNames = array_keys($this->mModules); // todo: optimize + $this->mFormats = & self :: $Formats; + $this->mFormatNames = array_keys($this->mFormats); // todo: optimize + $this->mResult = new ApiResult($this); $this->mShowVersions = false; $this->mEnableWrite = $enableWrite; - - $this->mRequest =& $request; + + $this->mRequest = & $request; $this->mInternalMode = ($request instanceof FauxRequest); + + $this->mSquidMaxage = 0; } public function & getRequest() { @@ -104,20 +109,24 @@ class ApiMain extends ApiBase { $this->dieUsage('Editing of this site is disabled. Make sure the $wgEnableWriteAPI=true; ' . 'statement is included in the site\'s LocalSettings.php file', 'readonly'); } - + + public function setCacheMaxAge($maxage) { + $this->mSquidMaxage = $maxage; + } + public function createPrinterByName($format) { return new $this->mFormats[$format] ($this, $format); } public function execute() { $this->profileIn(); - if($this->mInternalMode) + if ($this->mInternalMode) $this->executeAction(); else $this->executeActionWithErrorHandling(); $this->profileOut(); } - + protected function executeActionWithErrorHandling() { // In case an error occurs during data output, @@ -132,24 +141,25 @@ class ApiMain extends ApiBase { // If this fails, an unhandled exception should be thrown so that global error // handler will process and log it. // - + + // Error results should not be cached + $this->setCacheMaxAge(0); + // Printer may not be initialized if the extractRequestParams() fails for the main module if (!isset ($this->mPrinter)) { $this->mPrinter = $this->createPrinterByName(self :: API_DEFAULT_FORMAT); if ($this->mPrinter->getNeedsRawData()) $this->getResult()->setRawMode(); } - + if ($e instanceof UsageException) { // // User entered incorrect parameters - print usage screen // $errMessage = array ( - 'code' => $e->getCodeString(), - 'info' => $e->getMessage() - ); + 'code' => $e->getCodeString(), 'info' => $e->getMessage()); ApiResult :: setContent($errMessage, $this->makeHelpMsg()); - + } else { // // Something is seriously wrong @@ -160,7 +170,7 @@ class ApiMain extends ApiBase { ); ApiResult :: setContent($errMessage, "\n\n{$e->getTraceAsString()}\n\n"); } - + $headerStr = 'MediaWiki-API-Error: ' . $errMessage['code']; if ($e->getCode() === 0) header($headerStr, true); @@ -176,7 +186,13 @@ class ApiMain extends ApiBase { $this->mPrinter->safeProfileOut(); $this->printResult(true); } - + + // 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 + $expires = $this->mSquidMaxage == 0 ? 1 : time() + $this->mSquidMaxage; + header('Expires: ' . wfTimestamp(TS_RFC2822, $expires)); + header('Cache-Control: s-maxage=' . $this->mSquidMaxage . ', must-revalidate, max-age=0'); + ob_end_flush(); } @@ -192,29 +208,29 @@ class ApiMain extends ApiBase { $module = new $this->mModules[$action] ($this, $action); if (!$this->mInternalMode) { - + // See if custom printer is used - $this->mPrinter = $module->getCustomPrinter(); + $this->mPrinter = $module->getCustomPrinter(); if (is_null($this->mPrinter)) { // Create an appropriate printer $this->mPrinter = $this->createPrinterByName($format); } - + if ($this->mPrinter->getNeedsRawData()) $this->getResult()->setRawMode(); } - + // Execute $module->profileIn(); $module->execute(); $module->profileOut(); - + if (!$this->mInternalMode) { // Print result data $this->printResult(false); } } - + /** * Internal printer */ @@ -309,7 +325,7 @@ class ApiMain extends ApiBase { $vers[] = ApiBase :: getBaseVersion(); $vers[] = ApiFormatBase :: getBaseVersion(); $vers[] = ApiQueryBase :: getBaseVersion(); - $vers[] = ApiFormatFeedWrapper :: getVersion(); // not accessible with format=xxx + $vers[] = ApiFormatFeedWrapper :: getVersion(); // not accessible with format=xxx return $vers; } } diff --git a/includes/api/ApiOpenSearch.php b/includes/api/ApiOpenSearch.php index 9e5afcb8be..50b8e9cfc5 100644 --- a/includes/api/ApiOpenSearch.php +++ b/includes/api/ApiOpenSearch.php @@ -43,6 +43,9 @@ class ApiOpenSearch extends ApiBase { $search = null; extract($this->ExtractRequestParams()); + // Open search results may be stored for a very long time + $this->getMain()->setCacheMaxAge(1200); + $title = Title :: newFromText($search); if(!$title) return; // Return empty result