API: Add exception class as data to internal_api_error codes
authorBrad Jorsch <bjorsch@wikimedia.org>
Mon, 26 Nov 2018 18:31:41 +0000 (13:31 -0500)
committerBrad Jorsch <bjorsch@wikimedia.org>
Mon, 26 Nov 2018 18:42:07 +0000 (13:42 -0500)
The code for all uncaught exceptions will in the future be
"internal_api_error". If the client needs to know the class name for
some reason, it can check the new 'errorclass' data item on the error.

Change-Id: Ia9e32bbb8d17692203f4fbcee53a20e87be1776e

RELEASE-NOTES-1.33
includes/api/ApiErrorFormatter.php
includes/api/ApiMain.php
tests/phpunit/includes/api/ApiErrorFormatterTest.php
tests/phpunit/includes/api/ApiMainTest.php

index 422bbfa..677b1c1 100644 (file)
@@ -55,6 +55,12 @@ production.
 === Action API changes in 1.33 ===
 * (T198913) Added 'ApiOptions' hook.
 * The JSON formatversion=2 is no longer experimental.
+* Internal API errors (those with code beginning "internal_api_error") will
+  include the exception class name in a data field named "errorclass".
+  * Class names are not guaranteed to remain stable, and in particular database
+    exceptions will now include the "Wikimedia\Rdbms\" prefix in the class name.
+  * The code including an exception class name is deprecated. In the future,
+    all internal errors will use code "internal_api_error".
 * …
 
 === Action API internal changes in 1.33 ===
index ef28b73..a37ecc2 100644 (file)
@@ -211,6 +211,7 @@ class ApiErrorFormatter {
                                if ( !isset( $options['code'] ) ) {
                                        $class = preg_replace( '#^Wikimedia\\\Rdbms\\\#', '', get_class( $exception ) );
                                        $options['code'] = 'internal_api_error_' . $class;
+                                       $options['data']['errorclass'] = get_class( $exception );
                                }
                        }
                        $params = [ wfEscapeWikiText( $exception->getMessage() ) ];
index 162f0ce..bc76f8f 100644 (file)
@@ -1032,6 +1032,7 @@ class ApiMain extends ApiBase {
                        // TODO: Avoid embedding arbitrary class names in the error code.
                        $class = preg_replace( '#^Wikimedia\\\Rdbms\\\#', '', get_class( $e ) );
                        $code = 'internal_api_error_' . $class;
+                       $data = [ 'errorclass' => get_class( $e ) ];
                        if ( $config->get( 'ShowExceptionDetails' ) ) {
                                if ( $e instanceof ILocalizedException ) {
                                        $msg = $e->getMessageObject();
@@ -1045,7 +1046,7 @@ class ApiMain extends ApiBase {
                                $params = [ 'apierror-exceptioncaughttype', WebRequest::getRequestId(), get_class( $e ) ];
                        }
 
-                       $messages[] = ApiMessage::create( $params, $code );
+                       $messages[] = ApiMessage::create( $params, $code, $data );
                }
                return $messages;
        }
index 65a511d..312ef55 100644 (file)
@@ -599,7 +599,9 @@ class ApiErrorFormatterTest extends MediaWikiLangTestCase {
                                [
                                        'text' => '&#60;b&#62;Something broke!&#60;/b&#62;',
                                        'code' => 'internal_api_error_RuntimeException',
-                                       'data' => [],
+                                       'data' => [
+                                               'errorclass' => 'RuntimeException',
+                                       ],
                                ]
                        ],
                        'Normal exception, wrapped' => [
index 3299e73..9cb84e2 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 
+use Wikimedia\Rdbms\DBQueryError;
 use Wikimedia\TestingAccessWrapper;
 
 /**
@@ -1046,6 +1047,9 @@ class ApiMainTest extends ApiTestCase {
                                                [
                                                        'code' => 'internal_api_error_InvalidArgumentException',
                                                        'text' => "[$reqId] Exception caught: Random exception",
+                                                       'data' => [
+                                                               'errorclass' => InvalidArgumentException::class,
+                                                       ],
                                                ]
                                        ],
                                        'trace' => $trace,
@@ -1065,6 +1069,9 @@ class ApiMainTest extends ApiTestCase {
                                                        'code' => 'internal_api_error_DBQueryError',
                                                        'text' => "[$reqId] Exception caught: A database query error has occurred. " .
                                                                "This may indicate a bug in the software.",
+                                                       'data' => [
+                                                               'errorclass' => DBQueryError::class,
+                                                       ],
                                                ]
                                        ],
                                        'trace' => $dbtrace,
@@ -1083,6 +1090,9 @@ class ApiMainTest extends ApiTestCase {
                                                [
                                                        'code' => 'internal_api_error_MediaWiki\ShellDisabledError',
                                                        'text' => "[$reqId] Exception caught: " . $nsex->getMessage(),
+                                                       'data' => [
+                                                               'errorclass' => MediaWiki\ShellDisabledError::class,
+                                                       ],
                                                ]
                                        ],
                                        'trace' => $nstrace,