chore: migrate to RouteMatch context value

Bumps utopia-php/http to the latest fix/concurrency-shared-state, which
collapses the separate route / matchedPath / arguments context keys into
a single immutable RouteMatch under the 'match' key.

- Replace ->inject('route') / ->inject('matchedPath') with
  ->inject('match'), reading \$match->route / \$match->path.
- Replace the manual array_merge(\$route->getPathValues(), \$request->
  getParams()) workaround in api.php's shutdown hook with the framework-
  provided \$match->arguments — same data the action saw, no path-value
  reconstruction needed.
- Update GraphQL resolver to snapshot/restore the 'match' value instead
  of 'route'.
- Update top-level call sites in app/http.php that read from getResource
  ('route') to read getResource('match')->route.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
loks0n
2026-04-28 15:22:14 +01:00
co-authored by Claude Opus 4.7
parent b46ede4711
commit 2cc1f6a82a
6 changed files with 33 additions and 28 deletions
+7 -5
View File
@@ -54,7 +54,7 @@ use Utopia\Database\Validator\Authorization;
use Utopia\Domains\Domain;
use Utopia\DSN\DSN;
use Utopia\Http\Http;
use Utopia\Http\Route;
use Utopia\Http\RouteMatch;
use Utopia\Locale\Locale;
use Utopia\Logger\Adapter\Sentry;
use Utopia\Logger\Log;
@@ -848,8 +848,9 @@ Http::init()
->inject('authorization')
->inject('queueForDeletes')
->inject('executionsRetentionCount')
->inject('route')
->action(function (Http $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, Reader $geodb, Event $queueForEvents, Bus $bus, Executor $executor, array $platform, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization, DeleteEvent $queueForDeletes, int $executionsRetentionCount, ?Route $route) {
->inject('match')
->action(function (Http $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, Reader $geodb, Event $queueForEvents, Bus $bus, Executor $executor, array $platform, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization, DeleteEvent $queueForDeletes, int $executionsRetentionCount, ?RouteMatch $match) {
$route = $match?->route;
/*
* Appwrite Router
*/
@@ -1178,9 +1179,10 @@ Http::error()
->inject('bus')
->inject('devKey')
->inject('authorization')
->inject('route')
->action(function (Throwable $error, Http $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, Bus $bus, Document $devKey, Authorization $authorization, ?Route $route) {
->inject('match')
->action(function (Throwable $error, Http $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, Bus $bus, Document $devKey, Authorization $authorization, ?RouteMatch $match) {
$version = System::getEnv('_APP_VERSION', 'UNKNOWN');
$route = $match?->route;
$class = \get_class($error);
$code = $error->getCode();
$message = $error->getMessage();
+4 -3
View File
@@ -13,7 +13,7 @@ use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Validator\UID;
use Utopia\Http\Http;
use Utopia\Http\Route;
use Utopia\Http\RouteMatch;
use Utopia\Locale\Locale;
use Utopia\System\System;
use Utopia\Validator\Text;
@@ -287,8 +287,9 @@ Http::shutdown()
->inject('utopia')
->inject('response')
->inject('request')
->inject('route')
->action(function (Http $utopia, Response $response, Request $request, ?Route $route) {
->inject('match')
->action(function (Http $utopia, Response $response, Request $request, ?RouteMatch $match) {
$route = $match?->route;
$result = [];
$path = APP_STORAGE_CACHE . '/tests.json';
+12 -11
View File
@@ -40,6 +40,7 @@ use Utopia\Database\Validator\Authorization\Input;
use Utopia\Database\Validator\Roles;
use Utopia\Http\Http;
use Utopia\Http\Route;
use Utopia\Http\RouteMatch;
use Utopia\Span\Span;
use Utopia\System\System;
use Utopia\Telemetry\Adapter as Telemetry;
@@ -101,8 +102,9 @@ Http::init()
->inject('team')
->inject('apiKey')
->inject('authorization')
->inject('route')
->action(function (Http $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, AuditContext $auditContext, Document $project, User $user, ?Document $session, array $servers, string $mode, Document $team, ?Key $apiKey, Authorization $authorization, ?Route $route) {
->inject('match')
->action(function (Http $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, AuditContext $auditContext, Document $project, User $user, ?Document $session, array $servers, string $mode, Document $team, ?Key $apiKey, Authorization $authorization, ?RouteMatch $match) {
$route = $match?->route;
if ($route === null) {
throw new AppwriteException(AppwriteException::GENERAL_ROUTE_NOT_FOUND);
}
@@ -503,16 +505,17 @@ Http::init()
->inject('telemetry')
->inject('platform')
->inject('authorization')
->inject('route')
->inject('matchedPath')
->action(function (Http $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Messaging $queueForMessaging, AuditContext $auditContext, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Context $usage, Func $queueForFunctions, Mail $queueForMails, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, array $platform, Authorization $authorization, ?Route $route, string $path) {
->inject('match')
->action(function (Http $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Messaging $queueForMessaging, AuditContext $auditContext, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Context $usage, Func $queueForFunctions, Mail $queueForMails, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, array $platform, Authorization $authorization, ?RouteMatch $match) {
$response->setUser($user);
$request->setUser($user);
$route = $match?->route;
if ($route === null) {
throw new AppwriteException(AppwriteException::GENERAL_ROUTE_NOT_FOUND);
}
$path = $match->path;
$databaseType = match (true) {
@@ -813,8 +816,9 @@ Http::shutdown()
->inject('bus')
->inject('apiKey')
->inject('mode')
->inject('route')
->action(function (Http $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, AuditContext $auditContext, Audit $publisherForAudits, Context $usage, UsagePublisher $publisherForUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject, Authorization $authorization, callable $timelimit, EventProcessor $eventProcessor, Bus $bus, ?Key $apiKey, string $mode, ?Route $route) use ($parseLabel) {
->inject('match')
->action(function (Http $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, AuditContext $auditContext, Audit $publisherForAudits, Context $usage, UsagePublisher $publisherForUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject, Authorization $authorization, callable $timelimit, EventProcessor $eventProcessor, Bus $bus, ?Key $apiKey, string $mode, ?RouteMatch $match) use ($parseLabel) {
$route = $match?->route;
$responsePayload = $response->getPayload();
@@ -864,10 +868,7 @@ Http::shutdown()
}
}
$requestParams = array_merge(
$route?->getPathValues($request) ?? [],
$request->getParams(),
);
$requestParams = $match->arguments ?? [];
/**
* Abuse labels
+4 -3
View File
@@ -545,8 +545,8 @@ $swooleAdapter->onRequest(function ($utopiaRequest, $utopiaResponse) use ($files
$app->run($request, $response);
$route = $app->getResource('route');
Span::add('http.path', $route?->getPath() ?? 'unknown');
$match = $app->getResource('match');
Span::add('http.path', $match?->route->getPath() ?? 'unknown');
} catch (\Throwable $th) {
Span::error($th);
@@ -562,7 +562,8 @@ $swooleAdapter->onRequest(function ($utopiaRequest, $utopiaResponse) use ($files
}
try {
$route = $app->getResource('route');
$match = $app->getResource('match');
$route = $match?->route;
} catch (\Throwable $_th) {
$route = null;
}
Generated
+4 -4
View File
@@ -4275,12 +4275,12 @@
"source": {
"type": "git",
"url": "https://github.com/utopia-php/http.git",
"reference": "0707b7caff4ec0561027eba12ed045940e7b1b0d"
"reference": "41179392e58553f03467ba1d53710e4ecb542e03"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/http/zipball/0707b7caff4ec0561027eba12ed045940e7b1b0d",
"reference": "0707b7caff4ec0561027eba12ed045940e7b1b0d",
"url": "https://api.github.com/repos/utopia-php/http/zipball/41179392e58553f03467ba1d53710e4ecb542e03",
"reference": "41179392e58553f03467ba1d53710e4ecb542e03",
"shasum": ""
},
"require": {
@@ -4323,7 +4323,7 @@
"issues": "https://github.com/utopia-php/http/issues",
"source": "https://github.com/utopia-php/http/tree/fix/concurrency-shared-state"
},
"time": "2026-04-28T10:30:40+00:00"
"time": "2026-04-28T14:08:05+00:00"
},
{
"name": "utopia-php/image",
+2 -2
View File
@@ -360,7 +360,7 @@ class Resolvers
$lock->acquire();
try {
$original = $utopia->getResource('route');
$original = $utopia->getResource('match');
} catch (\Throwable $_th) {
$original = null;
}
@@ -408,7 +408,7 @@ class Resolvers
} finally {
if ($original !== null) {
$container = self::getResolverContainer($utopia);
$container->set('route', static fn () => $original);
$container->set('match', static fn () => $original);
}
$lock->release();