Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ docker-compose.web-installer.yml
.env.web-installer
docker-compose.web-installer.yml.**.backup
tests/playwright/screenshots
.claude/scheduled_tasks.lock
27 changes: 11 additions & 16 deletions app/controllers/general.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
use Utopia\Domains\Domain;
use Utopia\DSN\DSN;
use Utopia\Http\Http;
use Utopia\Http\RouteMatch;
use Utopia\Locale\Locale;
use Utopia\Logger\Adapter\Sentry;
use Utopia\Logger\Log;
Expand Down Expand Up @@ -847,23 +848,22 @@ function router(Http $utopia, Database $dbForPlatform, callable $getProjectDB, S
->inject('authorization')
->inject('queueForDeletes')
->inject('executionsRetentionCount')
->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) {
->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
*/
$hostname = $request->getHostname();
$platformHostnames = $platform['hostnames'] ?? [];
// Only run Router when external domain
if (!\in_array($hostname, $platformHostnames) || !empty($previewHostname)) {
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $bus, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount)) {
$utopia->getRoute()?->label('router', true);
}
router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $bus, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount);
}

/*
* Request format
*/
$route = $utopia->getRoute();
$request->setRoute($route);

if ($route === null) {
Expand Down Expand Up @@ -1147,9 +1147,7 @@ function router(Http $utopia, Database $dbForPlatform, callable $getProjectDB, S
$platformHostnames = $platform['hostnames'] ?? [];
// Only run Router when external domain
if (!in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) {
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $bus, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount)) {
$utopia->getRoute()?->label('router', true);
}
router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $bus, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount);
}

foreach ($cors->headers($request->getOrigin()) as $name => $value) {
Expand Down Expand Up @@ -1181,9 +1179,10 @@ function router(Http $utopia, Database $dbForPlatform, callable $getProjectDB, S
->inject('bus')
->inject('devKey')
->inject('authorization')
->action(function (Throwable $error, Http $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, Bus $bus, Document $devKey, Authorization $authorization) {
->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 = $utopia->getRoute();
$route = $match?->route;
$class = \get_class($error);
$code = $error->getCode();
$message = $error->getMessage();
Expand Down Expand Up @@ -1548,9 +1547,7 @@ function router(Http $utopia, Database $dbForPlatform, callable $getProjectDB, S
$template = new View(__DIR__ . '/../views/general/robots.phtml');
$response->text($template->render(false));
} else {
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $bus, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount)) {
$utopia->getRoute()?->label('router', true);
}
router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $bus, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount);
}
});

Expand Down Expand Up @@ -1582,9 +1579,7 @@ function router(Http $utopia, Database $dbForPlatform, callable $getProjectDB, S
$template = new View(__DIR__ . '/../views/general/humans.phtml');
$response->text($template->render(false));
} else {
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $bus, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount)) {
$utopia->getRoute()?->label('router', true);
}
router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $bus, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount);
}
});

Expand Down
6 changes: 4 additions & 2 deletions app/controllers/mock.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Utopia\Database\Helpers\Role;
use Utopia\Database\Validator\UID;
use Utopia\Http\Http;
use Utopia\Http\RouteMatch;
use Utopia\Locale\Locale;
use Utopia\System\System;
use Utopia\Validator\Text;
Expand Down Expand Up @@ -286,10 +287,11 @@
->inject('utopia')
->inject('response')
->inject('request')
->action(function (Http $utopia, Response $response, Request $request) {
->inject('match')
->action(function (Http $utopia, Response $response, Request $request, ?RouteMatch $match) {
$route = $match?->route;

$result = [];
$route = $utopia->getRoute();
$path = APP_STORAGE_CACHE . '/tests.json';
$tests = (\file_exists($path)) ? \json_decode(\file_get_contents($path), true) : [];

Expand Down
23 changes: 14 additions & 9 deletions app/controllers/shared/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
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;
Expand Down Expand Up @@ -100,8 +102,9 @@
->inject('team')
->inject('apiKey')
->inject('authorization')
->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 = $utopia->getRoute();
->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);
}
Expand Down Expand Up @@ -502,17 +505,19 @@
->inject('telemetry')
->inject('platform')
->inject('authorization')
->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) {
->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 = $utopia->getRoute();
$route = $match?->route;
if ($route === null) {
throw new AppwriteException(AppwriteException::GENERAL_ROUTE_NOT_FOUND);
}
$path = $match->path;


$path = $route->getMatchedPath();
$databaseType = match (true) {
str_contains($path, '/documentsdb') => DATABASE_TYPE_DOCUMENTSDB,
str_contains($path, '/vectorsdb') => DATABASE_TYPE_VECTORSDB,
Expand Down Expand Up @@ -628,7 +633,6 @@
$useCache = $route->getLabel('cache', false);
$storageCacheOperationsCounter = $telemetry->createCounter('storage.cache.operations.load');
if ($useCache) {
$route = $utopia->match($request);
$isImageTransformation = $route->getPath() === '/v1/storage/buckets/:bucketId/files/:fileId/preview';
$isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && ! $user->isPrivileged($authorization->getRoles());

Expand Down Expand Up @@ -811,7 +815,9 @@
->inject('bus')
->inject('apiKey')
->inject('mode')
->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) 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();

Expand Down Expand Up @@ -861,8 +867,7 @@
}
}

$route = $utopia->getRoute();
$requestParams = $route->getParamsValues();
$requestParams = $match->arguments ?? [];
Comment thread
greptile-apps[bot] marked this conversation as resolved.

/**
* Abuse labels
Expand Down
7 changes: 4 additions & 3 deletions app/controllers/shared/api/auth.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Utopia\Database\Document;
use Utopia\Database\Validator\Authorization;
use Utopia\Http\Http;
use Utopia\Http\RouteMatch;
use Utopia\System\System;

Http::init()
Expand All @@ -32,13 +33,13 @@

Http::init()
->groups(['auth'])
->inject('utopia')
->inject('request')
->inject('project')
->inject('geodb')
->inject('user')
->inject('authorization')
->action(function (Http $utopia, Request $request, Document $project, Reader $geodb, User $user, Authorization $authorization) {
->inject('match')
->action(function (Request $request, Document $project, Reader $geodb, User $user, Authorization $authorization, ?RouteMatch $match) {
$denylist = System::getEnv('_APP_CONSOLE_COUNTRIES_DENYLIST', '');
if (!empty($denylist && $project->getId() === 'console')) {
$countries = explode(',', $denylist);
Expand All @@ -49,7 +50,7 @@
}
}

$route = $utopia->match($request);
$route = $match?->route;

$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
$isAppUser = $user->isApp($authorization->getRoles());
Expand Down
24 changes: 12 additions & 12 deletions app/http.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
require_once __DIR__ . '/init.php';
require_once __DIR__ . '/init/span.php';

$registerRequestResources = require __DIR__ . '/init/resources/request.php';
$registerContext = require __DIR__ . '/init/resources/request.php';

use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
Expand Down Expand Up @@ -191,7 +191,7 @@ function dispatch(\Swoole\Http\Server $server, int $fd, int $type, $data = null)
});

$container->set('bus', function ($register) use ($swooleAdapter) {
return $register->get('bus')->setResolver(fn (string $name) => $swooleAdapter->getContainer()->get($name));
return $register->get('bus')->setResolver(fn (string $name) => $swooleAdapter->getContext()->get($name));
}, ['register']);

include __DIR__ . '/controllers/general.php';
Expand Down Expand Up @@ -502,7 +502,7 @@ function createDatabase(Http $app, string $resourceKey, string $dbName, array $c
});
});

$swooleAdapter->onRequest(function ($utopiaRequest, $utopiaResponse) use ($files, $swooleAdapter, $registerRequestResources) {
$swooleAdapter->onRequest(function ($utopiaRequest, $utopiaResponse) use ($files, $swooleAdapter, $registerContext) {
Span::init('http.request');

$request = new Request($utopiaRequest->getSwooleRequest());
Expand All @@ -522,15 +522,15 @@ function createDatabase(Http $app, string $resourceKey, string $dbName, array $c
return;
}

$requestContainer = $swooleAdapter->getContainer();
$requestContainer->set('container', fn () => $requestContainer);
$requestContainer->set('request', fn () => $request);
$requestContainer->set('response', fn () => $response);
$context = $swooleAdapter->getContext();
$context->set('container', fn () => $context);
$context->set('request', fn () => $request);
$context->set('response', fn () => $response);

$app = new Http($swooleAdapter, 'UTC');
$requestContainer->set('utopia', fn () => $app);
$context->set('utopia', fn () => $app);

$registerRequestResources($requestContainer);
$registerContext($context);

$app->setCompression(System::getEnv('_APP_COMPRESSION_ENABLED', 'enabled') === 'enabled');
$app->setCompressionMinSize(intval(System::getEnv('_APP_COMPRESSION_MIN_SIZE_BYTES', '1024'))); // 1KB
Expand All @@ -545,8 +545,8 @@ function createDatabase(Http $app, string $resourceKey, string $dbName, array $c

$app->run($request, $response);

$route = $app->getRoute();
Span::add('http.path', $route?->getPath() ?? 'unknown');
$match = $app->getResource('match');
Span::add('http.path', $match?->route->getPath() ?? 'unknown');
Comment thread
greptile-apps[bot] marked this conversation as resolved.
} catch (\Throwable $th) {
Span::error($th);

Expand All @@ -561,7 +561,7 @@ function createDatabase(Http $app, string $resourceKey, string $dbName, array $c
// All good, user is optional information for logger
}

$route = $app->getRoute();
$route = $app->getResource('match')?->route;

$log = $app->getResource("log");

Expand Down
13 changes: 7 additions & 6 deletions app/init/resources/request.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
use Utopia\Domains\Domain;
use Utopia\DSN\DSN;
use Utopia\Http\Http;
use Utopia\Http\RouteMatch;
use Utopia\Locale\Locale;
use Utopia\Logger\Log;
use Utopia\Pools\Group;
Expand Down Expand Up @@ -602,7 +603,7 @@
return $user;
}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform', 'store', 'proofForToken', 'authorization']);

$container->set('project', function ($dbForPlatform, $request, $console, $authorization, Http $utopia) {
$container->set('project', function ($dbForPlatform, $request, $console, $authorization, ?RouteMatch $match) {
/** @var Appwrite\Utopia\Request $request */
/** @var Utopia\Database\Database $dbForPlatform */
/** @var Utopia\Database\Document $console */
Expand All @@ -616,7 +617,7 @@
// These endpoints moved from /v1/projects/:projectId/<resource> to /v1/<resource>
// When accessed via the old alias path, extract projectId from the URI
$deprecatedProjectPathPrefix = '/v1/projects/';
$route = $utopia->match($request);
$route = $match?->route;
if (!empty($route)) {
$isDeprecatedAlias = \str_starts_with($request->getURI(), $deprecatedProjectPathPrefix) &&
!\str_starts_with($route->getPath(), $deprecatedProjectPathPrefix);
Expand All @@ -633,7 +634,7 @@
$project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId));

return $project;
}, ['dbForPlatform', 'request', 'console', 'authorization', 'utopia']);
}, ['dbForPlatform', 'request', 'console', 'authorization', 'match']);

$container->set('session', function (User $user, Store $store, Token $proofForToken) {
if ($user->isEmpty()) {
Expand Down Expand Up @@ -1100,12 +1101,12 @@
return $key;
}, ['request', 'project', 'servers', 'dbForPlatform', 'authorization']);

$container->set('team', function (Document $project, Database $dbForPlatform, Http $utopia, Request $request, Authorization $authorization) {
$container->set('team', function (Document $project, Database $dbForPlatform, ?RouteMatch $match, Request $request, Authorization $authorization) {
$teamInternalId = '';
if ($project->getId() !== 'console') {
$teamInternalId = $project->getAttribute('teamInternalId', '');
} else {
$route = $utopia->match($request);
$route = $match?->route;
$path = ! empty($route) ? $route->getPath() : $request->getURI();
$orgHeader = $request->getHeader('x-appwrite-organization', '');
if (str_starts_with($path, '/v1/projects/:projectId')) {
Expand Down Expand Up @@ -1141,7 +1142,7 @@
});

return $team;
}, ['project', 'dbForPlatform', 'utopia', 'request', 'authorization']);
}, ['project', 'dbForPlatform', 'match', 'request', 'authorization']);

$container->set('previewHostname', function (Request $request, ?Key $apiKey) {
$allowed = false;
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
"utopia-php/emails": "0.6.*",
"utopia-php/dns": "1.6.*",
"utopia-php/dsn": "0.2.1",
"utopia-php/http": "0.34.*",
"utopia-php/http": "dev-fix/concurrency-shared-state as 0.34.99",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Dev-branch dependency pinned to 1.9.x

utopia-php/http is locked to dev-fix/concurrency-shared-state as 0.34.99, an unmerged feature branch. The PR description notes this must be reverted before merging, but having it land on the release branch — even temporarily — means any build from 1.9.x pulls a mutable, non-stable reference that could change from under deployments. Until the upstream PR ships and a tagged release exists, merging this to 1.9.x poses a real stability risk.

"utopia-php/fetch": "0.5.*",
"utopia-php/validators": "0.2.*",
"utopia-php/image": "0.8.*",
Expand Down
Loading
Loading