Merge "Add 3D filetype for STL files"
[lhc/web/wiklou.git] / includes / api / ApiMain.php
index 604fdf9..d7586e0 100644 (file)
@@ -1,7 +1,5 @@
 <?php
 /**
- *
- *
  * Created on Sep 4, 2006
  *
  * Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
  */
 
 use MediaWiki\Logger\LoggerFactory;
+use MediaWiki\MediaWikiServices;
 use Wikimedia\Timestamp\TimestampException;
+use Wikimedia\Rdbms\DBQueryError;
+use Wikimedia\Rdbms\DBError;
 
 /**
  * This is the main API class, used for both external and internal processing.
@@ -160,6 +161,7 @@ class ApiMain extends ApiBase {
        private $mCacheMode = 'private';
        private $mCacheControl = [];
        private $mParamsUsed = [];
+       private $mParamsSensitive = [];
 
        /** @var bool|null Cached return value from self::lacksSameOriginSecurity() */
        private $lacksSameOriginSecurity = null;
@@ -234,6 +236,7 @@ class ApiMain extends ApiBase {
                                wfDebug( "API: stripping user credentials when the same-origin policy is not applied\n" );
                                $wgUser = new User();
                                $this->getContext()->setUser( $wgUser );
+                               $request->response()->header( 'MediaWiki-Login-Suppressed: true' );
                        }
                }
 
@@ -544,7 +547,7 @@ class ApiMain extends ApiBase {
                        $runTime = microtime( true ) - $t;
                        $this->logRequest( $runTime );
                        if ( $this->mModule->isWriteMode() && $this->getRequest()->wasPosted() ) {
-                               $this->getStats()->timing(
+                               MediaWikiServices::getInstance()->getStatsdDataFactory()->timing(
                                        'api.' . $this->mModule->getModuleName() . '.executeTiming', 1000 * $runTime
                                );
                        }
@@ -776,7 +779,8 @@ class ApiMain extends ApiBase {
 
                        if ( !$preflight ) {
                                $response->header(
-                                       'Access-Control-Expose-Headers: MediaWiki-API-Error, Retry-After, X-Database-Lag'
+                                       'Access-Control-Expose-Headers: MediaWiki-API-Error, Retry-After, X-Database-Lag, '
+                                       . 'MediaWiki-Login-Suppressed'
                                );
                        }
                }
@@ -1042,7 +1046,8 @@ class ApiMain extends ApiBase {
                } else {
                        // Something is seriously wrong
                        $config = $this->getConfig();
-                       $code = 'internal_api_error_' . get_class( $e );
+                       $class = preg_replace( '#^Wikimedia\\\Rdbms\\\#', '', get_class( $e ) );
+                       $code = 'internal_api_error_' . $class;
                        if ( ( $e instanceof DBQueryError ) && !$config->get( 'ShowSQLErrors' ) ) {
                                $params = [ 'apierror-databaseerror', WebRequest::getRequestId() ];
                        } else {
@@ -1228,6 +1233,35 @@ class ApiMain extends ApiBase {
                return $module;
        }
 
+       /**
+        * @return array
+        */
+       private function getMaxLag() {
+               $dbLag = MediaWikiServices::getInstance()->getDBLoadBalancer()->getMaxLag();
+               $lagInfo = [
+                       'host' => $dbLag[0],
+                       'lag' => $dbLag[1],
+                       'type' => 'db'
+               ];
+
+               $jobQueueLagFactor = $this->getConfig()->get( 'JobQueueIncludeInMaxLagFactor' );
+               if ( $jobQueueLagFactor ) {
+                       // Turn total number of jobs into seconds by using the configured value
+                       $totalJobs = array_sum( JobQueueGroup::singleton()->getQueueSizes() );
+                       $jobQueueLag = $totalJobs / (float)$jobQueueLagFactor;
+                       if ( $jobQueueLag > $lagInfo['lag'] ) {
+                               $lagInfo = [
+                                       'host' => wfHostname(), // XXX: Is there a better value that could be used?
+                                       'lag' => $jobQueueLag,
+                                       'type' => 'jobqueue',
+                                       'jobs' => $totalJobs,
+                               ];
+                       }
+               }
+
+               return $lagInfo;
+       }
+
        /**
         * Check the max lag if necessary
         * @param ApiBase $module Api module being used
@@ -1237,18 +1271,22 @@ class ApiMain extends ApiBase {
        protected function checkMaxLag( $module, $params ) {
                if ( $module->shouldCheckMaxlag() && isset( $params['maxlag'] ) ) {
                        $maxLag = $params['maxlag'];
-                       list( $host, $lag ) = wfGetLB()->getMaxLag();
-                       if ( $lag > $maxLag ) {
+                       $lagInfo = $this->getMaxLag();
+                       if ( $lagInfo['lag'] > $maxLag ) {
                                $response = $this->getRequest()->response();
 
                                $response->header( 'Retry-After: ' . max( intval( $maxLag ), 5 ) );
-                               $response->header( 'X-Database-Lag: ' . intval( $lag ) );
+                               $response->header( 'X-Database-Lag: ' . intval( $lagInfo['lag'] ) );
 
                                if ( $this->getConfig()->get( 'ShowHostnames' ) ) {
-                                       $this->dieWithError( [ 'apierror-maxlag', $lag, $host ] );
+                                       $this->dieWithError(
+                                               [ 'apierror-maxlag', $lagInfo['lag'], $lagInfo['host'] ],
+                                               'maxlag',
+                                               $lagInfo
+                                       );
                                }
 
-                               $this->dieWithError( [ 'apierror-maxlag-generic', $lag ], 'maxlag' );
+                               $this->dieWithError( [ 'apierror-maxlag-generic', $lagInfo['lag'] ], 'maxlag', $lagInfo );
                        }
                }
 
@@ -1601,13 +1639,17 @@ class ApiMain extends ApiBase {
                        " {$logCtx['ip']} " .
                        "T={$logCtx['timeSpentBackend']}ms";
 
+               $sensitive = array_flip( $this->getSensitiveParams() );
                foreach ( $this->getParamsUsed() as $name ) {
                        $value = $request->getVal( $name );
                        if ( $value === null ) {
                                continue;
                        }
 
-                       if ( strlen( $value ) > 256 ) {
+                       if ( isset( $sensitive[$name] ) ) {
+                               $value = '[redacted]';
+                               $encValue = '[redacted]';
+                       } elseif ( strlen( $value ) > 256 ) {
                                $value = substr( $value, 0, 256 );
                                $encValue = $this->encodeRequestLogValue( $value ) . '[...]';
                        } else {
@@ -1657,6 +1699,24 @@ class ApiMain extends ApiBase {
                $this->mParamsUsed += array_fill_keys( (array)$params, true );
        }
 
+       /**
+        * Get the request parameters that should be considered sensitive
+        * @since 1.29
+        * @return array
+        */
+       protected function getSensitiveParams() {
+               return array_keys( $this->mParamsSensitive );
+       }
+
+       /**
+        * Mark parameters as sensitive
+        * @since 1.29
+        * @param string|string[] $params
+        */
+       public function markParamsSensitive( $params ) {
+               $this->mParamsSensitive += array_fill_keys( (array)$params, true );
+       }
+
        /**
         * Get a request value, and register the fact that it was used, for logging.
         * @param string $name