aboutsummaryrefslogtreecommitdiffstats
path: root/includes/Rest/EntryPoint.php
diff options
context:
space:
mode:
authordaniel <dkinzler@wikimedia.org>2023-11-23 10:34:04 +0100
committerdaniel <dkinzler@wikimedia.org>2024-03-12 14:37:18 +0100
commitae9d8e60542aad435f3e42d145006cb180430234 (patch)
tree18cb5dcf5b4b6903ea49634f388ff604f01897a5 /includes/Rest/EntryPoint.php
parent5c87a85f236a500d7a9e92b92775b568eec8c16d (diff)
downloadmediawikicore-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.php154
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();
}
+
}