ResourceLoader: Factor out ResourceEntryPoint from load.php

The idea is that all entry points should share the code in the
MediaWikiEntryPoint base class. This change by itself doesn't achieve much, it should be followed up by a change moving request handling logic from ResourceLoader into ResourceEntryPoint.

Bug: T354216
Change-Id: Iadea44b7867f48a2be6ccbf00c0e56911a5af74e
This commit is contained in:
daniel 2023-11-23 22:55:36 +01:00 committed by James D. Forrester
parent 4eba3fa025
commit 4ea8c705a3
5 changed files with 160 additions and 30 deletions

View file

@ -1838,6 +1838,7 @@ $wgAutoloadLocalClasses = [
'MediaWiki\\ResourceLoader\\OOUIIconPackModule' => __DIR__ . '/includes/ResourceLoader/OOUIIconPackModule.php',
'MediaWiki\\ResourceLoader\\OOUIImageModule' => __DIR__ . '/includes/ResourceLoader/OOUIImageModule.php',
'MediaWiki\\ResourceLoader\\OOUIModule' => __DIR__ . '/includes/ResourceLoader/OOUIModule.php',
'MediaWiki\\ResourceLoader\\ResourceEntryPoint' => __DIR__ . '/includes/ResourceLoader/ResourceEntryPoint.php',
'MediaWiki\\ResourceLoader\\ResourceLoader' => __DIR__ . '/includes/ResourceLoader/ResourceLoader.php',
'MediaWiki\\ResourceLoader\\SiteModule' => __DIR__ . '/includes/ResourceLoader/SiteModule.php',
'MediaWiki\\ResourceLoader\\SiteStylesModule' => __DIR__ . '/includes/ResourceLoader/SiteStylesModule.php',

View file

@ -308,9 +308,11 @@ abstract class MediaWikiEntryPoint {
wfDebug( __METHOD__ . ': pre-send deferred updates completed' );
// Persist the session to avoid race conditions on subsequent requests by the client
$request->getSession()->save(); // T214471
wfDebug( __METHOD__ . ': session changes committed' );
if ( !defined( 'MW_NO_SESSION' ) ) {
// Persist the session to avoid race conditions on subsequent requests by the client
$request->getSession()->save(); // T214471
wfDebug( __METHOD__ . ': session changes committed' );
}
// Subsequent requests by the client should see the DB replication positions, as written
// to ChronologyProtector during the shutdown() call below.

View file

@ -0,0 +1,65 @@
<?php
/**
* Entry point implementation for @ref ResourceLoader, which serves static CSS/JavaScript
* via @ref MediaWiki\ResourceLoader\Module Module subclasses.
*
* @see /load.php The web entry point
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
* @ingroup entrypoint
* @ingroup ResourceLoader
*/
namespace MediaWiki\ResourceLoader;
use MediaWiki\MediaWikiEntryPoint;
use Profiler;
class ResourceEntryPoint extends MediaWikiEntryPoint {
/**
* Main entry point
*/
public function execute() {
$services = $this->getServiceContainer();
// Disable ChronologyProtector so that we don't wait for unrelated MediaWiki
// writes when getting database connections for ResourceLoader. (T192611)
$services->getChronologyProtector()->setEnabled( false );
$resourceLoader = $services->getResourceLoader();
$context = new Context(
$resourceLoader,
$this->getRequest()
);
// Respond to ResourceLoader request
$resourceLoader->respond( $context );
// Append any visible profiling data in a manner appropriate for the Content-Type
$profiler = Profiler::instance();
$profiler->setAllowOutput();
$profiler->logDataPageOutputOnly();
}
protected function doPrepareForOutput() {
// No-op.
// Do not call parent::doPrepareForOutput() to avoid
// commitMainTransaction() getting called.
}
}

View file

@ -1,7 +1,8 @@
<?php
/**
* The web entry point for @ref ResourceLoader, which serves static CSS/JavaScript
* via @ref MediaWiki\ResourceLoader\Module Module subclasses.
* The web entry point for @ref ResourceLoader, which serves static CSS/JavaScript.
*
* @see MediaWiki\ResourceLoader\ResourceEntryPoint The implementation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -25,8 +26,9 @@
* @author Trevor Parscal
*/
use MediaWiki\EntryPointEnvironment;
use MediaWiki\MediaWikiServices;
use MediaWiki\ResourceLoader\Context;
use MediaWiki\ResourceLoader\ResourceEntryPoint;
// This endpoint is supposed to be independent of request cookies and other
// details of the session. Enforce this constraint with respect to session use.
@ -36,27 +38,8 @@ define( 'MW_ENTRY_POINT', 'load' );
require __DIR__ . '/includes/WebStart.php';
wfLoadMain();
function wfLoadMain() {
global $wgRequest;
$services = MediaWikiServices::getInstance();
// Disable ChronologyProtector so that we don't wait for unrelated MediaWiki
// writes when getting database connections for ResourceLoader. (T192611)
$services->getChronologyProtector()->setEnabled( false );
$resourceLoader = $services->getResourceLoader();
$context = new Context( $resourceLoader, $wgRequest );
// Respond to ResourceLoader request
$resourceLoader->respond( $context );
// Append any visible profiling data in a manner appropriate for the Content-Type
$profiler = Profiler::instance();
$profiler->setAllowOutput();
$profiler->logDataPageOutputOnly();
$mediawiki = new MediaWiki();
$mediawiki->doPostOutputShutdown();
}
( new ResourceEntryPoint(
RequestContext::getMain(),
new EntryPointEnvironment(),
MediaWikiServices::getInstance()
) )->run();

View file

@ -0,0 +1,79 @@
<?php
namespace MediaWiki\Tests\Rest;
use MediaWiki\MainConfigNames;
use MediaWiki\Request\FauxRequest;
use MediaWiki\ResourceLoader\ResourceEntryPoint;
use MediaWiki\ResourceLoader\ResourceLoader;
use MediaWiki\Tests\MockEnvironment;
use Psr\Log\NullLogger;
use Wikimedia\DependencyStore\KeyValueDependencyStore;
/**
* @covers \MediaWiki\ResourceLoader\ResourceLoader
* @group Database
*/
class ResourceEntryPointTest extends \MediaWikiIntegrationTestCase {
protected function setUp(): void {
parent::setUp();
$this->overrideConfigValue( MainConfigNames::ShowExceptionDetails, true );
$this->setService( 'ResourceLoader', [ $this, 'newResourceLoader' ] );
}
public function newResourceLoader() {
$rl = new ResourceLoader(
$this->getServiceContainer()->getMainConfig(),
new NullLogger(),
new KeyValueDependencyStore( new \HashBagOStuff() ),
[
'loadScript' => '/w/load.php',
'maxageVersioned' => null,
'maxageUnversioned' => null,
]
);
$rl->register( include MW_INSTALL_PATH . '/resources/Resources.php' );
return $rl;
}
/**
* @param MockEnvironment $env
*
* @return ResourceEntryPoint
*/
private function getEntryPoint( MockEnvironment $env ): ResourceEntryPoint {
$entryPoint = new ResourceEntryPoint(
$env->makeFauxContext(),
$env,
$this->getServiceContainer()
);
return $entryPoint;
}
public function testResource() {
$uri = '/w/load.php';
$request = new FauxRequest( [ 'modules' => 'site' ] );
$request->setRequestURL( $uri );
$env = new MockEnvironment( $request );
$entryPoint = $this->getEntryPoint( $env );
$entryPoint->establishOutputBufferLevel();
$entryPoint->run();
// NOTE: MediaWikiEntryPoint::doPostOutputShutdown flushes all output buffers
$content = $entryPoint->captureOutput();
$this->assertStringContainsString( 'mw.loader.impl', $content );
$this->assertStringContainsString( 'site@', $content );
// TODO: Assert headers. We'll have to make ResourceLoader use WebResponse
// instead of calling the global header() function.
}
}