'phpfm' => 'ApiFormatPhp',
'xml' => 'ApiFormatXml',
'xmlfm' => 'ApiFormatXml',
- 'yaml' => 'ApiFormatYaml',
- 'yamlfm' => 'ApiFormatYaml',
'rawfm' => 'ApiFormatJson',
- 'txt' => 'ApiFormatTxt',
- 'txtfm' => 'ApiFormatTxt',
- 'dbg' => 'ApiFormatDbg',
- 'dbgfm' => 'ApiFormatDbg',
'none' => 'ApiFormatNone',
);
return;
}
// Logged out, send normal public headers below
- } elseif ( session_id() != '' ) {
+ } elseif ( MediaWiki\Session\SessionManager::getGlobalSession()->isPersistent() ) {
// Logged in or otherwise has session (e.g. anonymous users who have edited)
// Mark request private
$response->header( "Cache-Control: $privateCache" );
* @param array $params An array with the request parameters
*/
protected function setupExternalResponse( $module, $params ) {
- if ( !$this->getRequest()->wasPosted() && $module->mustBePosted() ) {
+ $request = $this->getRequest();
+ if ( !$request->wasPosted() && $module->mustBePosted() ) {
// Module requires POST. GET request might still be allowed
// if $wgDebugApi is true, otherwise fail.
$this->dieUsageMsgOrDebug( array( 'mustbeposted', $this->mAction ) );
// Create an appropriate printer
$this->mPrinter = $this->createPrinterByName( $params['format'] );
}
+
+ if ( $request->getProtocol() === 'http' && (
+ $request->getSession()->shouldForceHTTPS() ||
+ ( $this->getUser()->isLoggedIn() &&
+ $this->getUser()->requiresHTTPS() )
+ ) ) {
+ $this->logFeatureUsage( 'https-expected' );
+ $this->setWarning( 'HTTP used when HTTPS was expected' );
+ }
}
/**
$module = $this->setupModule();
$this->mModule = $module;
+ $this->setRequestExpectations( $module );
+
$this->checkExecutePermissions( $module );
if ( !$this->checkMaxLag( $module, $params ) ) {
}
}
+ /**
+ * Set database connection, query, and write expectations given this module request
+ * @param ApiBase $module
+ */
+ protected function setRequestExpectations( ApiBase $module ) {
+ $limits = $this->getConfig()->get( 'TrxProfilerLimits' );
+ $trxProfiler = Profiler::instance()->getTransactionProfiler();
+ if ( $this->getRequest()->wasPosted() ) {
+ if ( $module->isWriteMode() ) {
+ $trxProfiler->setExpectations( $limits['POST'], __METHOD__ );
+ } else {
+ $trxProfiler->setExpectations( $limits['POST-nonwrite'], __METHOD__ );
+ }
+ } else {
+ $trxProfiler->setExpectations( $limits['GET'], __METHOD__ );
+ }
+ }
+
/**
* Log the preceding request
- * @param int $time Time in seconds
+ * @param float $time Time in seconds
*/
protected function logRequest( $time ) {
$request = $this->getRequest();
- $milliseconds = $time === null ? '?' : round( $time * 1000 );
- $s = 'API' .
- ' ' . $request->getMethod() .
- ' ' . wfUrlencode( str_replace( ' ', '_', $this->getUser()->getName() ) ) .
- ' ' . $request->getIP() .
- ' T=' . $milliseconds . 'ms';
+ $logCtx = array(
+ 'dt' => date( 'c' ),
+ 'client_ip' => $request->getIP(),
+ 'user_agent' => $this->getUserAgent(),
+ 'wiki' => wfWikiID(),
+ 'time_backend_ms' => round( $time * 1000 ),
+ 'params' => array(),
+ );
+
+ // Construct space separated message for 'api' log channel
+ $msg = "API {$request->getMethod()} " .
+ wfUrlencode( str_replace( ' ', '_', $this->getUser()->getName() ) ) .
+ " {$logCtx['client_ip']} " .
+ "T={$logCtx['time_backend_ms']}ms";
+
foreach ( $this->getParamsUsed() as $name ) {
$value = $request->getVal( $name );
if ( $value === null ) {
continue;
}
- $s .= ' ' . $name . '=';
+
if ( strlen( $value ) > 256 ) {
- $encValue = $this->encodeRequestLogValue( substr( $value, 0, 256 ) );
- $s .= $encValue . '[...]';
+ $value = substr( $value, 0, 256 );
+ $encValue = $this->encodeRequestLogValue( $value ) . '[...]';
} else {
- $s .= $this->encodeRequestLogValue( $value );
+ $encValue = $this->encodeRequestLogValue( $value );
}
+
+ $logCtx['params'][$name] = $value;
+ $msg .= " {$name}={$encValue}";
}
- $s .= "\n";
- wfDebugLog( 'api', $s, 'private' );
+
+ wfDebugLog( 'api', $msg, 'private' );
+ // ApiRequest channel is for structured data consumers
+ wfDebugLog( 'ApiRequest', '', 'private', $logCtx );
}
/**
$this->getModuleManager()->addModule( $name, 'format', $class );
}
- /**
- * Get the array mapping module names to class names
- * @deprecated since 1.21, Use getModuleManager()'s methods instead.
- * @return array
- */
- function getModules() {
- return $this->getModuleManager()->getNamesWithClasses( 'action' );
- }
-
/**
* Returns the list of supported formats in form ( 'format' => 'ClassName' )
*