From: Brad Jorsch Date: Wed, 9 Nov 2016 16:59:05 +0000 (-0500) Subject: API: Pretty-printed responses should always use HTTP status 200 X-Git-Tag: 1.31.0-rc.0~4892^2 X-Git-Url: https://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/banques/Foo_bar?a=commitdiff_plain;h=44f8496104912253ca38053d159e1f0de1c949f9;p=lhc%2Fweb%2Fwiklou.git API: Pretty-printed responses should always use HTTP status 200 To accomplish this, the responsibility for setting the HTTP status code in the response is moved to ApiFormatBase. This also adds a line to the pretty-printed response and to ApiSandbox's output to indicate the status that would be used. Bug: T150344 Change-Id: Iaf0698ee1b93565d9b02b5a9aa8f93ceb135658b --- diff --git a/includes/api/ApiFormatBase.php b/includes/api/ApiFormatBase.php index 4c406a763b..67f54a8068 100644 --- a/includes/api/ApiFormatBase.php +++ b/includes/api/ApiFormatBase.php @@ -33,6 +33,7 @@ abstract class ApiFormatBase extends ApiBase { private $mIsHtml, $mFormat, $mUnescapeAmps, $mHelp; private $mBuffer, $mDisabled = false; private $mIsWrappedHtml = false; + private $mHttpStatus = false; protected $mForceDefaultParams = false; /** @@ -147,6 +148,23 @@ abstract class ApiFormatBase extends ApiBase { } } + /** + * Set the HTTP status code to be used for the response + * @since 1.29 + * @param int $code + */ + public function setHttpStatus( $code ) { + if ( $this->mDisabled ) { + return; + } + + if ( $this->getIsHtml() ) { + $this->mHttpStatus = $code; + } else { + $this->getMain()->getRequest()->response()->statusHeader( $code ); + } + } + /** * Initialize the printer function and prepare the output headers. * @param bool $unused Always false since 1.25 @@ -212,6 +230,18 @@ abstract class ApiFormatBase extends ApiBase { ApiHelp::fixHelpLinks( $header ) ) ); + + if ( $this->mHttpStatus && $this->mHttpStatus !== 200 ) { + $out->addHTML( + Html::rawElement( 'div', [ 'class' => 'api-pretty-header api-pretty-status' ], + $this->msg( + 'api-format-prettyprint-status', + $this->mHttpStatus, + HttpStatus::getMessage( $this->mHttpStatus ) + )->parse() + ) + ); + } } if ( Hooks::run( 'ApiFormatHighlight', [ $context, $result, $mime, $format ] ) ) { @@ -225,6 +255,8 @@ abstract class ApiFormatBase extends ApiBase { $time = microtime( true ) - $this->getConfig()->get( 'RequestTime' ); $json = FormatJson::encode( [ + 'status' => (int)( $this->mHttpStatus ?: 200 ), + 'statustext' => HttpStatus::getMessage( $this->mHttpStatus ?: 200 ), 'html' => $out->getHTML(), 'modules' => array_values( array_unique( array_merge( $out->getModules(), diff --git a/includes/api/ApiMain.php b/includes/api/ApiMain.php index 8deee5c8e1..a2da166a6c 100644 --- a/includes/api/ApiMain.php +++ b/includes/api/ApiMain.php @@ -572,11 +572,7 @@ class ApiMain extends ApiBase { $response = $this->getRequest()->response(); $headerStr = 'MediaWiki-API-Error: ' . $errCode; - if ( $e->getCode() === 0 ) { - $response->header( $headerStr ); - } else { - $response->header( $headerStr, true, $e->getCode() ); - } + $response->header( $headerStr ); // Reset and print just the error message ob_clean(); @@ -585,7 +581,7 @@ class ApiMain extends ApiBase { $this->createErrorPrinter(); try { - $this->printResult( true ); + $this->printResult( $e->getCode() ); } catch ( UsageException $ex ) { // The error printer itself is failing. Try suppressing its request // parameters and redo. @@ -595,7 +591,10 @@ class ApiMain extends ApiBase { $this->mPrinter = null; $this->createErrorPrinter(); $this->mPrinter->forceDefaultParams(); - $this->printResult( true ); + if ( $e->getCode() ) { + $response->statusHeader( 200 ); // Reset in case the fallback doesn't want a non-200 + } + $this->printResult( $e->getCode() ); } } @@ -1441,7 +1440,7 @@ class ApiMain extends ApiBase { MWDebug::appendDebugInfoToApiResult( $this->getContext(), $this->getResult() ); // Print result data - $this->printResult( false ); + $this->printResult(); } } @@ -1621,15 +1620,18 @@ class ApiMain extends ApiBase { /** * Print results using the current printer * - * @param bool $isError + * @param int $httpCode HTTP status code, or 0 to not change */ - protected function printResult( $isError ) { + protected function printResult( $httpCode = 0 ) { if ( $this->getConfig()->get( 'DebugAPI' ) !== false ) { $this->setWarning( 'SECURITY WARNING: $wgDebugAPI is enabled' ); } $printer = $this->mPrinter; $printer->initPrinter( false ); + if ( $httpCode ) { + $printer->setHttpStatus( $httpCode ); + } $printer->execute(); $printer->closePrinter(); } diff --git a/includes/api/i18n/en.json b/includes/api/i18n/en.json index fe73a56a5f..0f184d9f5d 100644 --- a/includes/api/i18n/en.json +++ b/includes/api/i18n/en.json @@ -1451,6 +1451,7 @@ "api-format-title": "MediaWiki API result", "api-format-prettyprint-header": "This is the HTML representation of the $1 format. HTML is good for debugging, but is unsuitable for application use.\n\nSpecify the format parameter to change the output format. To see the non-HTML representation of the $1 format, set format=$2.\n\nSee the [[mw:API|complete documentation]], or the [[Special:ApiHelp/main|API help]] for more information.", "api-format-prettyprint-header-only-html": "This is an HTML representation intended for debugging, and is unsuitable for application use.\n\nSee the [[mw:API|complete documentation]], or the [[Special:ApiHelp/main|API help]] for more information.", + "api-format-prettyprint-status": "This response would be returned with HTTP status $1 $2.", "api-pageset-param-titles": "A list of titles to work on.", "api-pageset-param-pageids": "A list of page IDs to work on.", diff --git a/includes/api/i18n/qqq.json b/includes/api/i18n/qqq.json index 95d6485383..f7c750e373 100644 --- a/includes/api/i18n/qqq.json +++ b/includes/api/i18n/qqq.json @@ -1349,6 +1349,7 @@ "api-format-title": "{{technical}}\nPage title when API output is pretty-printed in HTML.", "api-format-prettyprint-header": "{{technical}} Displayed as a header when API output is pretty-printed in HTML.\n\nParameters:\n* $1 - Format name\n* $2 - Non-pretty-printing module name", "api-format-prettyprint-header-only-html": "{{technical}} Displayed as a header when API output is pretty-printed in HTML, but there is no non-html module.\n\nParameters:\n* $1 - Format name", + "api-format-prettyprint-status": "{{technical}} Displayed as a header when API pretty-printed output is used for a response that uses an unusual HTTP status code.\n\nParameters:\n* $1 - HTTP status code (integer)\n* $2 - Standard English text for the status code.", "api-pageset-param-titles": "{{doc-apihelp-param|pageset|titles|description=the \"titles\" parameter in pageset-using modules}}", "api-pageset-param-pageids": "{{doc-apihelp-param|pageset|pageids|description=the \"pageids\" parameter in pageset-using modules}}", "api-pageset-param-revids": "{{doc-apihelp-param|pageset|revids|description=the \"revids\" parameter in pageset-using modules}}", diff --git a/resources/Resources.php b/resources/Resources.php index 2e4a15dc60..5c2f12ae2e 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -1867,6 +1867,7 @@ return [ 'apisandbox-continue', 'apisandbox-continue-clear', 'apisandbox-continue-help', + 'api-format-prettyprint-status', 'blanknamespace', ], ], diff --git a/resources/src/mediawiki.special/mediawiki.special.apisandbox.js b/resources/src/mediawiki.special/mediawiki.special.apisandbox.js index 98ed3eecfb..af4a8e946c 100644 --- a/resources/src/mediawiki.special/mediawiki.special.apisandbox.js +++ b/resources/src/mediawiki.special/mediawiki.special.apisandbox.js @@ -969,6 +969,14 @@ if ( data.modules.length ) { mw.loader.load( data.modules ); } + if ( data.status && data.status !== 200 ) { + $( '
' ) + .addClass( 'api-pretty-header api-pretty-status' ) + .append( + mw.message( 'api-format-prettyprint-status', data.status, data.statustext ).parse() + ) + .appendTo( $result ); + } $result.append( Util.parseHTML( data.html ) ); loadTime = data.time; } else if ( ( m = data.match( /][\s\S]*<\/pre>/ ) ) ) {