diff options
author | daniel <dkinzler@wikimedia.org> | 2023-11-23 10:34:04 +0100 |
---|---|---|
committer | daniel <dkinzler@wikimedia.org> | 2024-03-12 14:37:18 +0100 |
commit | ae9d8e60542aad435f3e42d145006cb180430234 (patch) | |
tree | 18cb5dcf5b4b6903ea49634f388ff604f01897a5 /includes/Rest/EntryPoint.php | |
parent | 5c87a85f236a500d7a9e92b92775b568eec8c16d (diff) | |
download | mediawikicore-ae9d8e60542aad435f3e42d145006cb180430234.tar.gz mediawikicore-ae9d8e60542aad435f3e42d145006cb180430234.zip |
Rest: Turn Rest\EntryPoint into a MediaWikiEntryPoint subclass
The idea is for all entry points to use the MediaWikiEntryPoint
base class, to improve consistency and testability.
Bug: T354216
Change-Id: I3678afe32c7c1a313d2dcb1808286c25ecd167eb
Diffstat (limited to 'includes/Rest/EntryPoint.php')
-rw-r--r-- | includes/Rest/EntryPoint.php | 154 |
1 files changed, 88 insertions, 66 deletions
diff --git a/includes/Rest/EntryPoint.php b/includes/Rest/EntryPoint.php index aecae45e26ed..ec8dfa37c751 100644 --- a/includes/Rest/EntryPoint.php +++ b/includes/Rest/EntryPoint.php @@ -3,14 +3,14 @@ namespace MediaWiki\Rest; use ExtensionRegistry; -use MediaWiki; use MediaWiki\Config\Config; use MediaWiki\Config\ServiceOptions; use MediaWiki\Context\IContextSource; use MediaWiki\Context\RequestContext; +use MediaWiki\EntryPointEnvironment; use MediaWiki\MainConfigNames; +use MediaWiki\MediaWikiEntryPoint; use MediaWiki\MediaWikiServices; -use MediaWiki\Request\WebResponse; use MediaWiki\Rest\BasicAccess\CompoundAuthorizer; use MediaWiki\Rest\BasicAccess\MWBasicAuthorizer; use MediaWiki\Rest\Reporter\MWErrorReporter; @@ -19,21 +19,18 @@ use MediaWiki\Title\Title; use MWExceptionRenderer; use Wikimedia\Message\ITextFormatter; -class EntryPoint { - /** @var RequestInterface */ - private $request; - /** @var WebResponse */ - private $webResponse; - /** @var Router */ - private $router; - /** @var RequestContext */ - private $context; - /** @var CorsUtils */ - private $cors; - /** @var ?RequestInterface */ - private static $mainRequest; +/** + * @internal + */ +class EntryPoint extends MediaWikiEntryPoint { + + private RequestInterface $request; + private ?Router $router = null; + private ?CorsUtils $cors = null; /** + * @internal Public for use in core tests + * * @param MediaWikiServices $services * @param IContextSource $context * @param RequestInterface $request @@ -42,7 +39,7 @@ class EntryPoint { * * @return Router */ - private static function createRouter( + public static function createRouter( MediaWikiServices $services, IContextSource $context, RequestInterface $request, @@ -84,64 +81,68 @@ class EntryPoint { } /** + * @internal * @return RequestInterface The RequestInterface object used by this entry point. */ public static function getMainRequest(): RequestInterface { - if ( self::$mainRequest === null ) { + static $mainRequest = null; + + if ( $mainRequest === null ) { $conf = MediaWikiServices::getInstance()->getMainConfig(); - self::$mainRequest = new RequestFromGlobals( [ + $mainRequest = new RequestFromGlobals( [ 'cookiePrefix' => $conf->get( MainConfigNames::CookiePrefix ) ] ); } - return self::$mainRequest; + + return $mainRequest; } - public static function main() { - // URL safety checks - global $wgRequest; + protected function doSetup() { + parent::doSetup(); $context = RequestContext::getMain(); // Set $wgTitle and the title in RequestContext, as in api.php global $wgTitle; - $wgTitle = Title::makeTitle( NS_SPECIAL, 'Badtitle/rest.php' ); + $wgTitle = Title::makeTitle( + NS_SPECIAL, + 'Badtitle/rest.php' + ); $context->setTitle( $wgTitle ); - $services = MediaWikiServices::getInstance(); - $conf = $services->getMainConfig(); - - $responseFactory = new ResponseFactory( self::getTextFormatters( $services ) ); - $responseFactory->setShowExceptionDetails( MWExceptionRenderer::shouldShowExceptionDetails() ); + $responseFactory = new ResponseFactory( $this->getTextFormatters() ); + $responseFactory->setShowExceptionDetails( + MWExceptionRenderer::shouldShowExceptionDetails() + ); - $cors = new CorsUtils( + $this->cors = new CorsUtils( new ServiceOptions( - CorsUtils::CONSTRUCTOR_OPTIONS, $conf + CorsUtils::CONSTRUCTOR_OPTIONS, + $this->getServiceContainer()->getMainConfig() ), $responseFactory, $context->getUser() ); - $request = self::getMainRequest(); - - $router = self::createRouter( $services, $context, $request, $responseFactory, $cors ); - - $entryPoint = new self( - $context, - $request, - $wgRequest->response(), - $router, - $cors - ); - $entryPoint->execute(); + if ( !$this->router ) { + $this->router = $this->createRouter( + $this->getServiceContainer(), + $context, + $this->request, + $responseFactory, + $this->cors + ); + } } /** * Get a TextFormatter array from MediaWikiServices * - * @param MediaWikiServices $services * @return ITextFormatter[] */ - private static function getTextFormatters( MediaWikiServices $services ) { + private function getTextFormatters() { + $services = $this->getServiceContainer(); + $code = $services->getContentLanguage()->getCode(); $langs = array_unique( [ $code, 'en' ] ); $textFormatters = []; @@ -150,11 +151,13 @@ class EntryPoint { foreach ( $langs as $lang ) { $textFormatters[] = $factory->getTextFormatter( $lang ); } + return $textFormatters; } /** * @param Config $conf + * * @return string[] */ private static function getRouteFiles( $conf ) { @@ -166,59 +169,80 @@ class EntryPoint { $conf->get( MainConfigNames::RestAPIAdditionalRouteFiles ) ); foreach ( $routeFiles as &$file ) { - if ( str_starts_with( $file, '/' ) ) { + if ( + str_starts_with( $file, '/' ) + ) { // Allow absolute paths on non-Windows - } elseif ( str_starts_with( $file, 'extensions/' ) ) { + } elseif ( + str_starts_with( $file, 'extensions/' ) + ) { // Support hacks like Wikibase.ci.php - $file = substr_replace( $file, $extensionsDir, 0, strlen( 'extensions' ) ); + $file = substr_replace( $file, $extensionsDir, + 0, strlen( 'extensions' ) ); } else { $file = "$IP/$file"; } } + return $routeFiles; } - public function __construct( RequestContext $context, RequestInterface $request, - WebResponse $webResponse, Router $router, CorsUtils $cors + public function __construct( + RequestInterface $request, + RequestContext $context, + EntryPointEnvironment $environment, + MediaWikiServices $mediaWikiServices ) { - $this->context = $context; + parent::__construct( $context, $environment, $mediaWikiServices ); + $this->request = $request; - $this->webResponse = $webResponse; + } + + /** + * Sets the router to use. + * Intended for testing. + * + * @param Router $router + */ + public function setRouter( Router $router ): void { $this->router = $router; - $this->cors = $cors; } public function execute() { - ob_start(); + $this->startOutputBuffer(); + $response = $this->cors->modifyResponse( $this->request, $this->router->execute( $this->request ) ); - $this->webResponse->header( - 'HTTP/' . $response->getProtocolVersion() . ' ' . - $response->getStatusCode() . ' ' . - $response->getReasonPhrase() ); + $webResponse = $this->getResponse(); + + $webResponse->header( + 'HTTP/' . $response->getProtocolVersion() . ' ' . $response->getStatusCode() . ' ' . + $response->getReasonPhrase() + ); foreach ( $response->getRawHeaderLines() as $line ) { - $this->webResponse->header( $line ); + $webResponse->header( $line ); } foreach ( $response->getCookies() as $cookie ) { - $this->webResponse->setCookie( + $webResponse->setCookie( $cookie['name'], $cookie['value'], $cookie['expiry'], - $cookie['options'] ); + $cookie['options'] + ); } // Clear all errors that might have been displayed if display_errors=On - ob_end_clean(); + $this->discardOutputBuffer(); $stream = $response->getBody(); $stream->rewind(); - MediaWiki::preOutputCommit( $this->context ); + $this->prepareForOutput(); if ( $stream instanceof CopyableStreamInterface ) { $stream->copyToStream( fopen( 'php://output', 'w' ) ); @@ -228,11 +252,9 @@ class EntryPoint { if ( $buffer === '' ) { break; } - echo $buffer; + $this->print( $buffer ); } } - - $mw = new MediaWiki; - $mw->doPostOutputShutdown(); } + } |