3 use Wikimedia\Http\HttpAcceptParser
;
4 use Wikimedia\Http\HttpAcceptNegotiator
;
7 * Request handler implementing a data interface for mediawiki pages.
10 * @author Daniel Kinzler
11 * @author Amir Sarabadanai
14 class PageDataRequestHandler
{
17 * Checks whether the request is complete, i.e. whether it contains all information needed
18 * to reply with page data.
20 * This does not check whether the request is valid and will actually produce a successful
23 * @param string|null $subPage
24 * @param WebRequest $request
29 public function canHandleRequest( $subPage, WebRequest
$request ) {
30 if ( $subPage === '' ||
$subPage === null ) {
31 if ( $request->getText( 'target', '' ) === '' ) {
38 $parts = explode( '/', $subPage, 2 );
41 if ( $slot === 'main' ||
$slot === '' ) {
50 * Main method for handling requests.
52 * @param string $subPage
53 * @param WebRequest $request The request parameters. Known parameters are:
54 * - title: the page title
55 * - format: the format
56 * - oldid|revision: the revision ID
57 * @param OutputPage $output
59 * @note: Instead of an output page, a WebResponse could be sufficient, but
60 * redirect logic is currently implemented in OutputPage.
64 public function handleRequest( $subPage, WebRequest
$request, OutputPage
$output ) {
65 // No matter what: The response is always public
66 $output->getRequest()->response()->header( 'Access-Control-Allow-Origin: *' );
68 if ( !$this->canHandleRequest( $subPage, $request ) ) {
69 throw new HttpError( 400, wfMessage( 'pagedata-bad-title', $subPage ) );
74 $parts = explode( '/', $subPage, 2 );
75 if ( $subPage !== '' ) {
78 $title = $request->getText( 'target', '' );
81 $revision = $request->getInt( 'oldid', $revision );
82 $revision = $request->getInt( 'revision', $revision );
84 if ( $title === null ||
$title === '' ) {
85 //TODO: different error message?
86 throw new HttpError( 400, wfMessage( 'pagedata-bad-title', $title ) );
90 $title = Title
::newFromTextThrow( $title );
91 } catch ( MalformedTitleException
$ex ) {
92 throw new HttpError( 400, wfMessage( 'pagedata-bad-title', $title ) );
95 $this->httpContentNegotiation( $request, $output, $title, $revision );
99 * Applies HTTP content negotiation.
100 * If the negotiation is successful, this method will set the appropriate redirect
101 * in the OutputPage object and return. Otherwise, an HttpError is thrown.
103 * @param WebRequest $request
104 * @param OutputPage $output
105 * @param Title $title
106 * @param int $revision The desired revision
110 public function httpContentNegotiation(
116 $contentHandler = ContentHandler
::getForTitle( $title );
117 $mimeTypes = $contentHandler->getSupportedFormats();
119 $headers = $request->getAllHeaders();
120 if ( isset( $headers['ACCEPT'] ) ) {
121 $parser = new HttpAcceptParser();
122 $accept = $parser->parseWeights( $headers['ACCEPT'] );
126 '*' => 0.1 // just to make extra sure
128 // prefer the default
129 $accept[$mimeTypes[0]] = 1;
132 $negotiator = new HttpAcceptNegotiator( $mimeTypes );
133 $format = $negotiator->getBestSupportedKey( $accept, null );
135 if ( $format === null ) {
136 $format = isset( $accept['text/html'] ) ?
'text/html' : null;
139 if ( $format === null ) {
140 $msg = wfMessage( 'pagedata-not-acceptable', implode( ', ', $mimeTypes ) );
141 throw new HttpError( 406, $msg );
144 $url = $this->getDocUrl( $title, $format, $revision );
145 $output->redirect( $url, 303 );
149 * Returns a url representing the given title.
151 * @param Title $title
152 * @param string|null $format The (normalized) format name, or ''
153 * @param int $revision
156 private function getDocUrl( Title
$title, $format = '', $revision = 0 ) {
159 if ( $revision > 0 ) {
160 $params['oldid'] = $revision;
163 if ( $format === 'text/html' ) {
164 return $title->getFullURL( $params );
167 $params[ 'action' ] = 'raw';
169 return $title->getFullURL( $params );