3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
21 use Wikimedia\Http\HttpAcceptParser
;
22 use Wikimedia\Http\HttpAcceptNegotiator
;
25 * Request handler implementing a data interface for mediawiki pages.
27 * @author Daniel Kinzler
28 * @author Amir Sarabadanai
30 class PageDataRequestHandler
{
33 * Checks whether the request is complete, i.e. whether it contains all information needed
34 * to reply with page data.
36 * This does not check whether the request is valid and will actually produce a successful
39 * @param string|null $subPage
40 * @param WebRequest $request
44 public function canHandleRequest( $subPage, WebRequest
$request ) {
45 if ( $subPage === '' ||
$subPage === null ) {
46 return $request->getText( 'target' ) !== '';
49 $parts = explode( '/', $subPage, 2 );
51 $title = $parts[1] ??
'';
52 return ( $slot === 'main' ||
$slot === '' ) && $title !== '';
56 * Main method for handling requests.
58 * @param string|null $subPage
59 * @param WebRequest $request The request parameters. Known parameters are:
60 * - title: the page title
61 * - format: the format
62 * - oldid|revision: the revision ID
63 * @param OutputPage $output
65 * @note Instead of an output page, a WebResponse could be sufficient, but
66 * redirect logic is currently implemented in OutputPage.
70 public function handleRequest( $subPage, WebRequest
$request, OutputPage
$output ) {
71 // No matter what: The response is always public
72 $output->getRequest()->response()->header( 'Access-Control-Allow-Origin: *' );
74 if ( !$this->canHandleRequest( $subPage, $request ) ) {
75 throw new HttpError( 400, wfMessage( 'pagedata-bad-title', $subPage ) );
80 if ( $subPage !== '' ) {
81 $parts = explode( '/', $subPage, 2 );
82 $title = $parts[1] ??
'';
84 $title = $request->getText( 'target' );
87 $revision = $request->getInt( 'oldid', $revision );
88 $revision = $request->getInt( 'revision', $revision );
90 if ( $title === null ||
$title === '' ) {
91 //TODO: different error message?
92 throw new HttpError( 400, wfMessage( 'pagedata-bad-title', $title ) );
96 $title = Title
::newFromTextThrow( $title );
97 } catch ( MalformedTitleException
$ex ) {
98 throw new HttpError( 400, wfMessage( 'pagedata-bad-title', $title ) );
101 $this->httpContentNegotiation( $request, $output, $title, $revision );
105 * Applies HTTP content negotiation.
106 * If the negotiation is successful, this method will set the appropriate redirect
107 * in the OutputPage object and return. Otherwise, an HttpError is thrown.
109 * @param WebRequest $request
110 * @param OutputPage $output
111 * @param Title $title
112 * @param int $revision The desired revision
116 public function httpContentNegotiation(
122 $contentHandler = ContentHandler
::getForTitle( $title );
123 $mimeTypes = $contentHandler->getSupportedFormats();
125 $acceptHeader = $request->getHeader( 'Accept' );
126 if ( $acceptHeader !== false ) {
127 $parser = new HttpAcceptParser();
128 $accept = $parser->parseWeights( $acceptHeader );
132 '*' => 0.1 // just to make extra sure
134 // prefer the default
135 $accept[$mimeTypes[0]] = 1;
138 $negotiator = new HttpAcceptNegotiator( $mimeTypes );
139 $format = $negotiator->getBestSupportedKey( $accept );
141 if ( $format === null ) {
142 $format = isset( $accept['text/html'] ) ?
'text/html' : null;
145 if ( $format === null ) {
146 $msg = wfMessage( 'pagedata-not-acceptable', implode( ', ', $mimeTypes ) );
147 throw new HttpError( 406, $msg );
150 $url = $this->getDocUrl( $title, $format, $revision );
151 $output->redirect( $url, 303 );
155 * Returns a url representing the given title.
157 * @param Title $title
158 * @param string|null $format The (normalized) format name, or ''
159 * @param int $revision
162 private function getDocUrl( Title
$title, $format = '', $revision = 0 ) {
165 if ( $revision > 0 ) {
166 $params['oldid'] = $revision;
169 if ( $format === 'text/html' ) {
170 return $title->getFullURL( $params );
173 $params[ 'action' ] = 'raw';
175 return $title->getFullURL( $params );