MediaWiki  master
PageHTMLHandler.php
Go to the documentation of this file.
1 <?php
2 
3 namespace MediaWiki\Rest\Handler;
4 
5 use Config;
7 use Exception;
8 use GuzzleHttp\Psr7\Uri;
9 use LogicException;
17 use TitleFormatter;
18 use UIDGenerator;
20 use WebRequest;
23 
36  private const MAX_AGE_200 = 5;
37 
39  private $restClient;
40 
42  private $htmlResponse;
43 
51  public function __construct(
56  VirtualRESTServiceClient $virtualRESTServiceClient
57  ) {
59 
60  $this->restClient = $virtualRESTServiceClient;
61  }
62 
68  private function fetchHtmlFromRESTBase( LinkTarget $title ): array {
69  if ( $this->htmlResponse !== null ) {
70  return $this->htmlResponse;
71  }
72 
73  list( , $service ) = $this->restClient->getMountAndService( '/restbase/ ' );
74  if ( !$service ) {
75  try {
76  $restConfig = $this->config->get( 'VirtualRestConfig' );
77  if ( !isset( $restConfig['modules']['restbase'] ) ) {
78  throw new ConfigException(
79  __CLASS__ . " requires restbase module configured for VirtualRestConfig"
80  );
81  }
82  $this->restClient->mount( '/restbase/',
83  new RestbaseVirtualRESTService( $restConfig['modules']['restbase'] ) );
84  } catch ( Exception $e ) {
85  // This would usually be config exception, but let's fail on any exception
86  throw new LocalizedHttpException( MessageValue::new( 'rest-html-backend-error' ), 500 );
87  }
88  }
89 
90  $this->htmlResponse = $this->restClient->run( [
91  'method' => 'GET',
92  'url' => '/restbase/local/v1/page/html/' .
93  urlencode( $this->titleFormatter->getPrefixedDBkey( $title ) ) .
94  '?redirect=false'
95  ] );
96  return $this->htmlResponse;
97  }
98 
104  private function fetch200HtmlFromRESTBase( LinkTarget $title ): array {
105  $restbaseResp = $this->fetchHtmlFromRESTBase( $title );
106  if ( $restbaseResp['code'] !== 200 ) {
107  throw new LocalizedHttpException(
108  MessageValue::new( 'rest-html-backend-error' ),
109  $restbaseResp['code']
110  );
111  }
112  return $restbaseResp;
113  }
114 
118  private function constructHtmlUrl(): string {
119  $wr = new WebRequest();
120  $urlParts = wfParseUrl( $wr->getFullRequestURL() );
121  $currentPathParts = explode( '/', $urlParts['path'] );
122  $currentPathParts[ count( $currentPathParts ) - 1 ] = 'html';
123  $urlParts['path'] = implode( '/', $currentPathParts );
124  return Uri::fromParts( $urlParts );
125  }
126 
133  public function run( string $title, string $htmlType ): Response {
134  $titleObj = $this->getTitle();
135  if ( !$titleObj || !$titleObj->getArticleID() ) {
136  throw new LocalizedHttpException(
137  MessageValue::new( 'rest-nonexistent-title' )->plaintextParams( $title ),
138  404
139  );
140  }
141 
142  if ( !$this->isAccessible( $titleObj ) ) {
143  throw new LocalizedHttpException(
144  MessageValue::new( 'rest-permission-denied-title' )->plaintextParams( $title ),
145  403
146  );
147  }
148 
149  $revision = $this->getLatestRevision();
150  if ( !$revision ) {
151  throw new LocalizedHttpException(
152  MessageValue::new( 'rest-no-revision' )->plaintextParams( $title ),
153  404
154  );
155  }
156 
157  switch ( $htmlType ) {
158  case 'bare':
159  $body = $this->constructMetadata( $titleObj, $revision );
160  $body['html_url'] = $this->constructHtmlUrl();
161  $response = $this->getResponseFactory()->createJson( $body );
162  break;
163  case 'html':
164  $restbaseResp = $this->fetch200HtmlFromRESTBase( $titleObj );
165  $response = $this->getResponseFactory()->create();
166  $response->setHeader( 'Content-Type', $restbaseResp[ 'headers' ][ 'content-type' ] );
167  $response->setBody( new StringStream( $restbaseResp[ 'body' ] ) );
168  break;
169  case 'with_html':
170  $restbaseResp = $this->fetch200HtmlFromRESTBase( $titleObj );
171  $body = $this->constructMetadata( $titleObj, $revision );
172  $body['html'] = $restbaseResp['body'];
173  $response = $this->getResponseFactory()->createJson( $body );
174  break;
175  default:
176  throw new LogicException( "Unknown HTML type $htmlType" );
177  }
178 
179  $response->setHeader( 'Cache-Control', 'max-age=' . self::MAX_AGE_200 );
180  return $response;
181  }
182 
190  protected function getETag(): ?string {
191  $title = $this->getTitle();
192  if ( !$title || !$title->getArticleID() || !$this->isAccessible( $title ) ) {
193  return null;
194  }
195 
196  if ( $this->getValidatedParams()['html_type'] === 'bare' ) {
197  return '"' . $this->getLatestRevision()->getId() . '"';
198  }
199 
200  $restbaseRes = $this->fetch200HtmlFromRESTBase( $title );
201  return $restbaseRes['headers']['etag'] ?? null;
202  }
203 
208  protected function getLastModified(): ?string {
209  $title = $this->getTitle();
210  if ( !$title || !$title->getArticleID() || !$this->isAccessible( $title ) ) {
211  return null;
212  }
213 
214  if ( $this->getValidatedParams()['html_type'] === 'bare' ) {
215  return $this->getLatestRevision()->getTimestamp();
216  }
217 
218  $restbaseRes = $this->fetch200HtmlFromRESTBase( $title );
219  $restbaseEtag = $restbaseRes['headers']['etag'] ?? null;
220  if ( !$restbaseEtag ) {
221  return null;
222  }
223 
224  $etagComponents = [];
225  if ( !preg_match( '/^(?:W\/)?"?[^"\/]+(?:\/([^"\/]+))"?$/',
226  $restbaseEtag, $etagComponents )
227  ) {
228  return null;
229  }
230 
231  return UIDGenerator::getTimestampFromUUIDv1( $etagComponents[1] ) ?: null;
232  }
233 
234  public function getParamSettings(): array {
235  $parentSettings = parent::getParamSettings();
236  $parentSettings['html_type'] = [
237  self::PARAM_SOURCE => 'path',
238  ParamValidator::PARAM_TYPE => [ 'bare', 'html', 'with_html' ],
239  ParamValidator::PARAM_REQUIRED => true,
240  ];
241  return $parentSettings;
242  }
243 }
MediaWiki\Rest\Handler\LatestPageContentHandler\$permissionManager
PermissionManager $permissionManager
Definition: LatestPageContentHandler.php:22
MediaWiki\Rest\Handler\PageHTMLHandler\__construct
__construct(Config $config, PermissionManager $permissionManager, RevisionLookup $revisionLookup, TitleFormatter $titleFormatter, VirtualRESTServiceClient $virtualRESTServiceClient)
Definition: PageHTMLHandler.php:51
MediaWiki\Rest\Handler
Definition: ActionModuleBasedHandler.php:3
MediaWiki\Rest\Handler\getResponseFactory
getResponseFactory()
Get the ResponseFactory which can be used to generate Response objects.
Definition: Handler.php:104
$response
$response
Definition: opensearch_desc.php:44
MediaWiki\Rest\StringStream
A stream class which uses a string as the underlying storage.
Definition: StringStream.php:16
MediaWiki\Rest\Handler\PageHTMLHandler\getLastModified
getLastModified()
Definition: PageHTMLHandler.php:208
UIDGenerator
Class for getting statistically unique IDs.
Definition: UIDGenerator.php:31
Revision\RevisionLookup
Service for looking up page revisions.
Definition: RevisionLookup.php:38
Wikimedia\Message\MessageValue
Value object representing a message for i18n.
Definition: MessageValue.php:14
MediaWiki\Rest\Handler\PageHTMLHandler\MAX_AGE_200
const MAX_AGE_200
Definition: PageHTMLHandler.php:36
MediaWiki\Rest\Handler\LatestPageContentHandler\$revisionLookup
RevisionLookup $revisionLookup
Definition: LatestPageContentHandler.php:25
MediaWiki\Rest\Handler\PageHTMLHandler\getETag
getETag()
Returns an ETag representing a page's source.
Definition: PageHTMLHandler.php:190
Config
Interface for configuration instances.
Definition: Config.php:28
MediaWiki\Rest\Handler\LatestPageContentHandler
Definition: LatestPageContentHandler.php:16
wfParseUrl
wfParseUrl( $url)
parse_url() work-alike, but non-broken.
Definition: GlobalFunctions.php:793
VirtualRESTServiceClient
Virtual HTTP service client loosely styled after a Virtual File System.
Definition: VirtualRESTServiceClient.php:45
MediaWiki\Rest\Response
Definition: Response.php:8
ConfigException
Exceptions for config failures.
Definition: ConfigException.php:28
$title
$title
Definition: testCompression.php:38
MediaWiki\Rest\Handler\getValidatedParams
getValidatedParams()
Fetch the validated parameters.
Definition: Handler.php:200
MediaWiki\Rest\Handler\LatestPageContentHandler\getLatestRevision
getLatestRevision()
Definition: LatestPageContentHandler.php:73
MediaWiki\Permissions\PermissionManager
A service class for checking permissions To obtain an instance, use MediaWikiServices::getInstance()-...
Definition: PermissionManager.php:49
MediaWiki\Rest\Handler\LatestPageContentHandler\constructMetadata
constructMetadata(Title $titleObject, RevisionRecord $revision)
Definition: LatestPageContentHandler.php:89
MediaWiki\Rest\Handler\LatestPageContentHandler\$titleFormatter
TitleFormatter $titleFormatter
Definition: LatestPageContentHandler.php:28
MediaWiki\Rest\Handler\LatestPageContentHandler\isAccessible
isAccessible( $titleObject)
Definition: LatestPageContentHandler.php:85
WebRequest
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form stripping il...
Definition: WebRequest.php:43
MediaWiki\Rest\Handler\PageHTMLHandler\run
run(string $title, string $htmlType)
Definition: PageHTMLHandler.php:133
MediaWiki\Rest\Handler\LatestPageContentHandler\$config
Config $config
Definition: LatestPageContentHandler.php:19
TitleFormatter
A title formatter service for MediaWiki.
Definition: TitleFormatter.php:34
MediaWiki\Rest\Handler\PageHTMLHandler\fetch200HtmlFromRESTBase
fetch200HtmlFromRESTBase(LinkTarget $title)
Definition: PageHTMLHandler.php:104
Wikimedia\Message\MessageValue\new
static new( $key, $params=[])
Static constructor for easier chaining of ->params() methods.
Definition: MessageValue.php:38
RestbaseVirtualRESTService
Virtual HTTP service client for RESTBase.
Definition: RestbaseVirtualRESTService.php:25
MediaWiki\Rest\Handler\PageHTMLHandler\fetchHtmlFromRESTBase
fetchHtmlFromRESTBase(LinkTarget $title)
Definition: PageHTMLHandler.php:68
MediaWiki\Rest\Handler\PageHTMLHandler\constructHtmlUrl
constructHtmlUrl()
Definition: PageHTMLHandler.php:118
MediaWiki\Rest\Handler\LatestPageContentHandler\getTitle
getTitle()
Definition: LatestPageContentHandler.php:63
MediaWiki\Linker\LinkTarget
Definition: LinkTarget.php:26
MediaWiki\Rest\Handler\PageHTMLHandler\$restClient
VirtualRESTServiceClient $restClient
Definition: PageHTMLHandler.php:39
Wikimedia\ParamValidator\ParamValidator
Service for formatting and validating API parameters.
Definition: ParamValidator.php:42
MediaWiki\Rest\Handler\PageHTMLHandler
Definition: PageHTMLHandler.php:35
MediaWiki\Rest\Handler\PageHTMLHandler\getParamSettings
getParamSettings()
Fetch ParamValidator settings for parameters.
Definition: PageHTMLHandler.php:234
MediaWiki\Rest\LocalizedHttpException
Definition: LocalizedHttpException.php:7
MediaWiki\Rest\Handler\PageHTMLHandler\$htmlResponse
array $htmlResponse
Definition: PageHTMLHandler.php:42
UIDGenerator\getTimestampFromUUIDv1
static getTimestampFromUUIDv1(string $uuid, int $format=TS_MW)
Get timestamp in a specified format from UUIDv1.
Definition: UIDGenerator.php:111