From bba1a0f2f92a722d60115c00f03244492eccfd30 Mon Sep 17 00:00:00 2001 From: Brad Jorsch Date: Mon, 19 Aug 2019 12:45:56 -0400 Subject: [PATCH] API: Warn about POST without Content-Type HHVM sniffs the content type and so probably correctly guesses application/x-www-form-urlencoded and fills in $_POST, while PHP 7 does not sniff and so doesn't fill in $_POST. Since there are clients that have been expecting the HHVM behavior, give a warning both to let them know and so we can have some idea of how many such clients there are. This also adds any warnings and errors as an HTML comment at the top of the auto-generated help page, to hopefully make it easier for people getting that unexpectedly to find out why. Bug: T230735 Change-Id: I017b7afe808844d74d376f6436894a5a2f525a9f --- includes/api/ApiHelp.php | 17 +++++++++++++++++ includes/api/ApiMain.php | 6 ++++++ includes/api/i18n/en.json | 1 + includes/api/i18n/qqq.json | 1 + 4 files changed, 25 insertions(+) diff --git a/includes/api/ApiHelp.php b/includes/api/ApiHelp.php index 988957b6d8..2627715d5a 100644 --- a/includes/api/ApiHelp.php +++ b/includes/api/ApiHelp.php @@ -66,6 +66,23 @@ class ApiHelp extends ApiBase { ApiResult::setSubelementsList( $data, 'help' ); $result->addValue( null, $this->getModuleName(), $data ); } else { + // Show any errors at the top of the HTML + $transform = [ + 'Types' => [ 'AssocAsObject' => true ], + 'Strip' => 'all', + ]; + $errors = array_filter( [ + 'errors' => $this->getResult()->getResultData( [ 'errors' ], $transform ), + 'warnings' => $this->getResult()->getResultData( [ 'warnings' ], $transform ), + ] ); + if ( $errors ) { + $json = FormatJson::encode( $errors, true, FormatJson::UTF8_OK ); + // Escape any "--", some parsers might interpret that as end-of-comment. + // The above already escaped any "<" and ">". + $json = str_replace( '--', '-\u002D', $json ); + $html = "\n$html"; + } + $result->reset(); $result->addValue( null, 'text', $html, ApiResult::NO_SIZE_CHECK ); $result->addValue( null, 'mime', 'text/html', ApiResult::NO_SIZE_CHECK ); diff --git a/includes/api/ApiMain.php b/includes/api/ApiMain.php index 554ab6a285..428024a054 100644 --- a/includes/api/ApiMain.php +++ b/includes/api/ApiMain.php @@ -1539,6 +1539,12 @@ class ApiMain extends ApiBase { $this->dieWithErrorOrDebug( [ 'apierror-mustbeposted', $this->mAction ] ); } + if ( $request->wasPosted() && !$request->getHeader( 'Content-Type' ) ) { + $this->addDeprecation( + 'apiwarn-deprecation-post-without-content-type', 'post-without-content-type' + ); + } + // See if custom printer is used $this->mPrinter = $module->getCustomPrinter(); if ( is_null( $this->mPrinter ) ) { diff --git a/includes/api/i18n/en.json b/includes/api/i18n/en.json index 6625863716..8b42a07e8e 100644 --- a/includes/api/i18n/en.json +++ b/includes/api/i18n/en.json @@ -1908,6 +1908,7 @@ "apiwarn-deprecation-missingparam": "Because $1 was not specified, a legacy format has been used for the output. This format is deprecated, and in the future the new format will always be used.", "apiwarn-deprecation-parameter": "The parameter $1 has been deprecated.", "apiwarn-deprecation-parse-headitems": "prop=headitems is deprecated since MediaWiki 1.28. Use prop=headhtml when creating new HTML documents, or prop=modules|jsconfigvars when updating a document client-side.", + "apiwarn-deprecation-post-without-content-type": "A POST request was made without a Content-Type header. This does not work reliably.", "apiwarn-deprecation-purge-get": "Use of action=purge via GET is deprecated. Use POST instead.", "apiwarn-deprecation-withreplacement": "$1 has been deprecated. Please use $2 instead.", "apiwarn-difftohidden": "Couldn't diff to r$1: content is hidden.", diff --git a/includes/api/i18n/qqq.json b/includes/api/i18n/qqq.json index d5de23f9bf..87f056bb04 100644 --- a/includes/api/i18n/qqq.json +++ b/includes/api/i18n/qqq.json @@ -1795,6 +1795,7 @@ "apiwarn-deprecation-missingparam": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.", "apiwarn-deprecation-parameter": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.", "apiwarn-deprecation-parse-headitems": "{{doc-apierror}}", + "apiwarn-deprecation-post-without-content-type": "{{doc-apierror}}", "apiwarn-deprecation-purge-get": "{{doc-apierror}}", "apiwarn-deprecation-withreplacement": "{{doc-apierror}}\n\nParameters:\n* $1 - Query string fragment that is deprecated, e.g. \"action=tokens\".\n* $2 - Query string fragment to use instead, e.g. \"action=tokens\".", "apiwarn-difftohidden": "{{doc-apierror}}\n\nParameters:\n* $1 - Revision ID number.\n\n\"r\" is short for \"revision\". You may translate it.", -- 2.20.1