*/
protected function handleException( $e ) {
// T65145: Rollback any open database transactions
- if ( !( $e instanceof ApiUsageException || $e instanceof UsageException ) ) {
- // UsageExceptions are intentional, so don't rollback if that's the case
+ if ( !$e instanceof ApiUsageException ) {
+ // ApiUsageExceptions are intentional, so don't rollback if that's the case
MWExceptionHandler::rollbackMasterChangesAndLog( $e );
}
$this->addWarning( $error );
}
}
- } catch ( UsageException $ex ) {
- // The error printer itself is failing. Try suppressing its request
- // parameters and redo.
- $failed = true;
- $this->addWarning(
- [ 'apiwarn-errorprinterfailed-ex', $ex->getMessage() ], 'errorprinterfailed'
- );
}
if ( $failed ) {
$this->mPrinter = null;
foreach ( $requestedHeaders as $rHeader ) {
$rHeader = strtolower( trim( $rHeader ) );
if ( !isset( $allowedAuthorHeaders[$rHeader] ) ) {
- wfDebugLog( 'api', 'CORS preflight failed on requested header: ' . $rHeader );
+ LoggerFactory::getInstance( 'api-warning' )->warning(
+ 'CORS preflight failed on requested header: {header}', [
+ 'header' => $rHeader
+ ]
+ );
return false;
}
}
* If an ApiUsageException, errors/warnings will be extracted from the
* embedded StatusValue.
*
- * If a base UsageException, the getMessageArray() method will be used to
- * extract the code and English message for a single error (no warnings).
- *
* Any other exception will be returned with a generic code and wrapper
* text around the exception's (presumably English) message as a single
* error (no warnings).
}
} elseif ( $type !== 'error' ) {
// None of the rest have any messages for non-error types
- } elseif ( $e instanceof UsageException ) {
- // User entered incorrect parameters - generate error response
- $data = Wikimedia\quietCall( [ $e, 'getMessageArray' ] );
- $code = $data['code'];
- $info = $data['info'];
- unset( $data['code'], $data['info'] );
- $messages[] = new ApiRawMessage( [ '$1', $info ], $code, $data );
} else {
// Something is seriously wrong
$config = $this->getConfig();
+ // 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();
$params = [ 'apierror-exceptioncaughttype', WebRequest::getRequestId(), get_class( $e ) ];
}
- $messages[] = ApiMessage::create( $params, $code );
+ $messages[] = ApiMessage::create( $params, $code, $data );
}
return $messages;
}
// Add errors from the exception
$modulePath = $e instanceof ApiUsageException ? $e->getModulePath() : null;
foreach ( $this->errorMessagesFromException( $e, 'error' ) as $msg ) {
- $errorCodes[$msg->getApiCode()] = true;
+ if ( ApiErrorFormatter::isValidApiCode( $msg->getApiCode() ) ) {
+ $errorCodes[$msg->getApiCode()] = true;
+ } else {
+ LoggerFactory::getInstance( 'api-warning' )->error( 'Invalid API error code "{code}"', [
+ 'code' => $msg->getApiCode(),
+ 'exception' => $e,
+ ] );
+ $errorCodes['<invalid-code>'] = true;
+ }
$formatter->addError( $modulePath, $msg );
}
foreach ( $this->errorMessagesFromException( $e, 'warning' ) as $msg ) {
} else {
$path = null;
}
- if ( $e instanceof ApiUsageException || $e instanceof UsageException ) {
+ if ( $e instanceof ApiUsageException ) {
$link = wfExpandUrl( wfScript( 'api' ) );
$result->addContentValue(
$path,
if ( $numLagged >= ceil( $replicaCount / 2 ) ) {
$laggedServers = implode( ', ', $laggedServers );
wfDebugLog(
- 'api-readonly',
+ 'api-readonly', // Deprecate this channel in favor of api-warning?
"Api request failed as read only because the following DBs are lagged: $laggedServers"
);
+ LoggerFactory::getInstance( 'api-warning' )->warning(
+ "Api request failed as read only because the following DBs are lagged: {laggeddbs}", [
+ 'laggeddbs' => $laggedServers,
+ ]
+ );
$this->dieWithError(
'readonly_lag',
* @param array $params An array with the request parameters
*/
protected function setupExternalResponse( $module, $params ) {
+ $validMethods = [ 'GET', 'HEAD', 'POST', 'OPTIONS' ];
$request = $this->getRequest();
+
+ if ( !in_array( $request->getMethod(), $validMethods ) ) {
+ $this->dieWithError( 'apierror-invalidmethod', null, null, 405 );
+ }
+
if ( !$request->wasPosted() && $module->mustBePosted() ) {
// Module requires POST. GET request might still be allowed
// if $wgDebugApi is true, otherwise fail.