13use Wikimedia\ObjectFactory;
115 $cacheData = $this->cacheBag->get( $this->
getCacheKey() );
116 if ( $cacheData && $cacheData[
'CONFIG-HASH'] === $this->
getConfigHash() ) {
117 unset( $cacheData[
'CONFIG-HASH'] );
128 return $this->cacheBag->makeKey( __CLASS__,
'1' );
137 if ( $this->configHash ===
null ) {
138 $this->configHash = md5( json_encode( [
152 if ( $this->routesFromFiles ===
null ) {
153 $this->routeFileTimestamps = [];
154 foreach ( $this->routeFiles as $fileName ) {
155 $this->routeFileTimestamps[$fileName] = filemtime( $fileName );
156 $routes = json_decode( file_get_contents( $fileName ),
true );
157 if ( $this->routesFromFiles ===
null ) {
158 $this->routesFromFiles = $routes;
160 $this->routesFromFiles = array_merge( $this->routesFromFiles, $routes );
173 if ( $this->routeFileTimestamps ===
null ) {
174 $this->routeFileTimestamps = [];
175 foreach ( $this->routeFiles as $fileName ) {
176 $this->routeFileTimestamps[$fileName] = filemtime( $fileName );
189 $iterator =
new AppendIterator;
191 $iterator->append(
new \ArrayIterator( $this->extraRoutes ) );
201 if ( $this->matchers ===
null ) {
205 foreach ( $cacheData as $method => $data ) {
210 $methods = $spec[
'method'] ?? [
'GET' ];
211 if ( !is_array( $methods ) ) {
212 $methods = [ $methods ];
214 foreach ( $methods as $method ) {
223 foreach (
$matchers as $method => $matcher ) {
224 $cacheData[$method] = $matcher->getCacheData();
226 $this->cacheBag->set( $this->
getCacheKey(), $cacheData );
241 if ( strlen( $this->rootPath ) > strlen(
$path ) ||
242 substr_compare(
$path, $this->rootPath, 0, strlen( $this->rootPath ) ) !== 0
246 return substr(
$path, strlen( $this->rootPath ) );
259 public function getRouteUrl( $route, $pathParams = [], $queryParams = [] ) {
260 foreach ( $pathParams as $param => $value ) {
263 $route = str_replace(
'{' . $param .
'}', rawurlencode( $value ), $route );
266 $url = $this->baseUrl . $this->rootPath . $route;
279 if ( $relPath ===
false ) {
280 return $this->responseFactory->createLocalizedHttpError( 404,
282 ->plaintextParams(
$path, $this->rootPath )
288 $matcher =
$matchers[$requestMethod] ??
null;
289 $match = $matcher ? $matcher->
match( $relPath ) :
null;
293 if ( !$match && $requestMethod ===
'HEAD' && isset(
$matchers[
'GET'] ) ) {
303 if ( $this->cors && $requestMethod ===
'OPTIONS' ) {
304 return $this->cors->createPreflightResponse( $allowed );
308 $response = $this->responseFactory->createLocalizedHttpError( 405,
310 ->textParams( $requestMethod )
311 ->commaListParams( $allowed )
312 ->numParams( count( $allowed ) )
314 $response->setHeader(
'Allow', $allowed );
318 return $this->responseFactory->createLocalizedHttpError( 404,
320 ->plaintextParams( $relPath )
326 $request->
setPathParams( array_map(
'rawurldecode', $match[
'params'] ) );
327 $handler = $this->
createHandler( $request, $match[
'userData'] );
332 return $this->responseFactory->createFromException( $e );
345 foreach ( $this->
getMatchers() as $allowedMethod => $allowedMatcher ) {
346 if ( $allowedMatcher->match( $relPath ) ) {
347 $allowed[] = $allowedMethod;
352 in_array(
'GET', $allowed ) ? array_merge( [
'HEAD' ], $allowed ) : $allowed
363 $objectFactorySpec = array_intersect_key(
370 'optional_services' =>
true
374 $handler = $this->objectFactory->createObject( $objectFactorySpec );
375 $handler->
init( $this, $request, $spec, $this->authority, $this->responseFactory, $this->hookContainer );
388 $authResult = $this->basicAuth->authorize( $handler->getRequest(), $handler );
390 return $this->responseFactory->createHttpError( 403, [
'error' => $authResult ] );
394 $handler->validate( $this->restValidator );
397 $earlyResponse = $handler->checkPreconditions();
398 if ( $earlyResponse ) {
399 return $earlyResponse;
403 $response = $handler->execute();
404 if ( !( $response instanceof ResponseInterface ) ) {
405 $response = $this->responseFactory->createFromReturnValue( $response );
409 $handler->applyConditionalResponseHeaders( $response );
wfAppendQuery( $url, $query)
Append a query string to an existing URL, which may or may not already have query string parameters a...
Class representing a cache/ephemeral data store.