diff --git a/app/config/collections.php b/app/config/collections.php index 7b8c35e104..bc4db6bce6 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -2744,7 +2744,7 @@ $collections = [ 'filters' => [], ], [ - '$id' => ID::custom('response'), + '$id' => ID::custom('body'), 'type' => Database::VAR_STRING, 'format' => '', 'size' => 1000000, @@ -2755,7 +2755,7 @@ $collections = [ 'filters' => [], ], [ - '$id' => ID::custom('stderr'), + '$id' => ID::custom('errors'), 'type' => Database::VAR_STRING, 'format' => '', 'size' => 1000000, @@ -2766,7 +2766,7 @@ $collections = [ 'filters' => [], ], [ - '$id' => ID::custom('stdout'), + '$id' => ID::custom('logs'), 'type' => Database::VAR_STRING, 'format' => '', 'size' => 1000000, @@ -2787,6 +2787,17 @@ $collections = [ 'array' => false, 'filters' => [], ], + [ + '$id' => ID::custom('headers'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json'], + ], [ '$id' => ID::custom('duration'), 'type' => Database::VAR_FLOAT, diff --git a/app/config/runtimes.php b/app/config/runtimes.php index b226e295b2..2cd73c1b70 100644 --- a/app/config/runtimes.php +++ b/app/config/runtimes.php @@ -13,6 +13,4 @@ $allowList = empty(App::getEnv('_APP_FUNCTIONS_RUNTIMES')) ? [] : \explode(',', $runtimes = $runtimes->getAll(true, $allowList); -$runtimes['php-8.1']['image'] = 'meldiron/php:v3-8.1'; - return $runtimes; diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index b237888a9a..83bb63dc43 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -13,6 +13,7 @@ use Utopia\Database\ID; use Utopia\Database\Permission; use Utopia\Database\Role; use Utopia\Database\Validator\UID; +use Utopia\Validator\Assoc; use Appwrite\Usage\Stats; use Utopia\Storage\Device; use Utopia\Storage\Validator\File; @@ -1057,8 +1058,11 @@ App::post('/v1/functions/:functionId/executions') ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) ->param('functionId', '', new UID(), 'Function ID.') - ->param('data', '', new Text(8192), 'String of custom data to send to function.', true) + ->param('body', '', new Text(8192), 'HTTP body of execution. Default value is empty string.', true) ->param('async', false, new Boolean(), 'Execute code in the background. Default value is false.', true) + ->param('path', '/', new Text(2048), 'HTTP path of execution. Default value is /', true) + ->param('method', 'GET', new Whitelist([ 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS' ], true), 'HTTP method of execution. Default value is GET.', true) + ->param('headers', [], new Assoc(), 'HTP headers of execution. Defaults to empty.', true) ->inject('response') ->inject('project') ->inject('dbForProject') @@ -1067,7 +1071,7 @@ App::post('/v1/functions/:functionId/executions') ->inject('usage') ->inject('mode') ->inject('queueForFunctions') - ->action(function (string $functionId, string $data, bool $async, Response $response, Document $project, Database $dbForProject, Document $user, Event $events, Stats $usage, string $mode, Func $queueForFunctions) { + ->action(function (string $functionId, string $body, bool $async, string $path, string $method, array $headers, Response $response, Document $project, Database $dbForProject, Document $user, Event $events, Stats $usage, string $mode, Func $queueForFunctions) { $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); @@ -1122,8 +1126,10 @@ App::post('/v1/functions/:functionId/executions') 'trigger' => 'http', // http / schedule / event 'status' => $async ? 'waiting' : 'processing', // waiting / processing / completed / failed 'statusCode' => 0, - 'response' => '', - 'stderr' => '', + 'body' => '', + 'headers' => [], + 'errors' => '', + 'logs' => '', 'duration' => 0.0, 'search' => implode(' ', [$functionId, $executionId]), ]))); @@ -1159,7 +1165,10 @@ App::post('/v1/functions/:functionId/executions') ->setType('http') ->setExecution($execution) ->setFunction($function) - ->setData($data) + ->setBody($body) + ->setHeaders($headers) + ->setPath($path) + ->setMethod($method) ->setJWT($jwt) ->setProject($project) ->setUser($user) @@ -1195,22 +1204,25 @@ App::post('/v1/functions/:functionId/executions') projectId: $project->getId(), deploymentId: $deployment->getId(), version: $function->getAttribute('version'), - payload: $data, + body: $body, variables: $vars, timeout: $function->getAttribute('timeout', 0), image: $runtime['image'], source: $build->getAttribute('path', ''), entrypoint: $deployment->getAttribute('entrypoint', ''), + path: $path, + method: $method, + headers: $headers, ); - /** Update execution status */ $status = $executionResponse['statusCode'] >= 500 ? 'failed' : 'completed'; $execution->setAttribute('status', $status); $execution->setAttribute('statusCode', $executionResponse['statusCode']); - $execution->setAttribute('response', $executionResponse['body']); - $execution->setAttribute('stdout', $executionResponse['logs']); - $execution->setAttribute('stderr', $executionResponse['errors']); + $execution->setAttribute('headers', $executionResponse['headers']); + $execution->setAttribute('body', $executionResponse['body']); + $execution->setAttribute('logs', $executionResponse['logs']); + $execution->setAttribute('errors', $executionResponse['errors']); $execution->setAttribute('duration', $executionResponse['duration']); } catch (\Throwable $th) { $interval = (new \DateTime())->diff(new \DateTime($execution->getCreatedAt())); @@ -1218,7 +1230,7 @@ App::post('/v1/functions/:functionId/executions') ->setAttribute('duration', (float)$interval->format('%s.%f')) ->setAttribute('status', 'failed') ->setAttribute('statusCode', $th->getCode()) - ->setAttribute('stderr', $th->getMessage()); + ->setAttribute('errors', $th->getMessage()); Console::error($th->getMessage()); } @@ -1236,8 +1248,8 @@ App::post('/v1/functions/:functionId/executions') $isAppUser = Auth::isAppUser($roles); if (!$isPrivilegedUser && !$isAppUser) { - $execution->setAttribute('stdout', ''); - $execution->setAttribute('stderr', ''); + $execution->setAttribute('logs', ''); + $execution->setAttribute('errors', ''); } $response @@ -1306,8 +1318,8 @@ App::get('/v1/functions/:functionId/executions') $isAppUser = Auth::isAppUser($roles); if (!$isPrivilegedUser && !$isAppUser) { $results = array_map(function ($execution) { - $execution->setAttribute('stdout', ''); - $execution->setAttribute('stderr', ''); + $execution->setAttribute('logs', ''); + $execution->setAttribute('errors', ''); return $execution; }, $results); } @@ -1358,8 +1370,8 @@ App::get('/v1/functions/:functionId/executions/:executionId') $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); if (!$isPrivilegedUser && !$isAppUser) { - $execution->setAttribute('stdout', ''); - $execution->setAttribute('stderr', ''); + $execution->setAttribute('logs', ''); + $execution->setAttribute('errors', ''); } $response->dynamic($execution, Response::MODEL_EXECUTION); diff --git a/app/workers/functions.php b/app/workers/functions.php index 51659a4c70..6145c9e31e 100644 --- a/app/workers/functions.php +++ b/app/workers/functions.php @@ -34,6 +34,9 @@ Server::setResource('execute', function () { Document $function, string $trigger, string $data = null, + string $path, + string $method, + array $headers, ?Document $user = null, string $jwt = null, string $event = null, @@ -86,8 +89,10 @@ Server::setResource('execute', function () { 'trigger' => $trigger, 'status' => 'waiting', 'statusCode' => 0, - 'response' => '', - 'stderr' => '', + 'body' => '', + 'headers' => [], + 'errors' => '', + 'logs' => '', 'duration' => 0.0, 'search' => implode(' ', [$functionId, $executionId]), ])); @@ -125,17 +130,21 @@ Server::setResource('execute', function () { /** Execute function */ try { + \var_dump($build->getAttribute('path', '')); $client = new Executor(App::getEnv('_APP_EXECUTOR_HOST')); $executionResponse = $client->createExecution( projectId: $project->getId(), deploymentId: $deploymentId, version: $function->getAttribute('version'), - payload: $vars['APPWRITE_FUNCTION_DATA'] ?? '', + body: $vars['APPWRITE_FUNCTION_DATA'] ?? '', variables: $vars, timeout: $function->getAttribute('timeout', 0), image: $runtime['image'], source: $build->getAttribute('path', ''), entrypoint: $deployment->getAttribute('entrypoint', ''), + path: $path, + method: $method, + headers: $headers, ); $status = $executionResponse['statusCode'] >= 500 ? 'failed' : 'completed'; @@ -144,9 +153,10 @@ Server::setResource('execute', function () { $execution ->setAttribute('status', $status) ->setAttribute('statusCode', $executionResponse['statusCode']) - ->setAttribute('response', $executionResponse['body']) - ->setAttribute('stdout', $executionResponse['logs']) - ->setAttribute('stderr', $executionResponse['errors']) + ->setAttribute('headers', $executionResponse['headers']) + ->setAttribute('body', $executionResponse['body']) + ->setAttribute('logs', $executionResponse['logs']) + ->setAttribute('errors', $executionResponse['errors']) ->setAttribute('duration', $executionResponse['duration']); } catch (\Throwable $th) { $interval = (new \DateTime())->diff(new \DateTime($execution->getCreatedAt())); @@ -154,7 +164,7 @@ Server::setResource('execute', function () { ->setAttribute('duration', (float)$interval->format('%s.%f')) ->setAttribute('status', 'failed') ->setAttribute('statusCode', $th->getCode()) - ->setAttribute('stderr', $th->getMessage()); + ->setAttribute('errors', $th->getMessage()); Console::error($th->getTraceAsString()); Console::error($th->getFile()); @@ -283,7 +293,10 @@ $server->job() user: $user, data: null, executionId: null, - jwt: null + jwt: null, + path: $payload['path'], + method: $payload['method'], + headers: $payload['headers'], ); Console::success('Triggered function: ' . $events[0]); } @@ -312,6 +325,9 @@ $server->job() user: $user, jwt: $jwt, statsd: $statsd, + path: $payload['path'], + method: $payload['method'], + headers: $payload['headers'], ); break; case 'schedule': @@ -328,6 +344,9 @@ $server->job() user: null, jwt: null, statsd: $statsd, + path: $payload['path'], + method: $payload['method'], + headers: $payload['headers'], ); break; } diff --git a/composer.lock b/composer.lock index 4ee60140ac..dc33c8026a 100644 --- a/composer.lock +++ b/composer.lock @@ -2140,22 +2140,23 @@ }, { "name": "utopia-php/logger", - "version": "0.3.0", + "version": "0.3.1", "source": { "type": "git", "url": "https://github.com/utopia-php/logger.git", - "reference": "079656cb5169ca9600861eda0b6819199e3d4a57" + "reference": "de623f1ec1c672c795d113dd25c5bf212f7ef4fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/logger/zipball/079656cb5169ca9600861eda0b6819199e3d4a57", - "reference": "079656cb5169ca9600861eda0b6819199e3d4a57", + "url": "https://api.github.com/repos/utopia-php/logger/zipball/de623f1ec1c672c795d113dd25c5bf212f7ef4fc", + "reference": "de623f1ec1c672c795d113dd25c5bf212f7ef4fc", "shasum": "" }, "require": { "php": ">=8.0" }, "require-dev": { + "phpstan/phpstan": "1.9.x-dev", "phpunit/phpunit": "^9.3", "vimeo/psalm": "4.0.1" }, @@ -2169,20 +2170,6 @@ "license": [ "MIT" ], - "authors": [ - { - "name": "Eldad Fux", - "email": "eldad@appwrite.io" - }, - { - "name": "Matej Bačo", - "email": "matej@appwrite.io" - }, - { - "name": "Christy Jacob", - "email": "christy@appwrite.io" - } - ], "description": "Utopia Logger library is simple and lite library for logging information, such as errors or warnings. This library is aiming to be as simple and easy to learn and use.", "keywords": [ "appsignal", @@ -2200,22 +2187,22 @@ ], "support": { "issues": "https://github.com/utopia-php/logger/issues", - "source": "https://github.com/utopia-php/logger/tree/0.3.0" + "source": "https://github.com/utopia-php/logger/tree/0.3.1" }, - "time": "2022-03-18T10:56:57+00:00" + "time": "2023-02-10T15:52:50+00:00" }, { "name": "utopia-php/messaging", - "version": "0.1.0", + "version": "0.1.1", "source": { "type": "git", "url": "https://github.com/utopia-php/messaging.git", - "reference": "501272fad666f06bec8f130076862e7981a73f8c" + "reference": "a75d66ddd59b834ab500a4878a2c084e6572604a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/messaging/zipball/501272fad666f06bec8f130076862e7981a73f8c", - "reference": "501272fad666f06bec8f130076862e7981a73f8c", + "url": "https://api.github.com/repos/utopia-php/messaging/zipball/a75d66ddd59b834ab500a4878a2c084e6572604a", + "reference": "a75d66ddd59b834ab500a4878a2c084e6572604a", "shasum": "" }, "require": { @@ -2223,9 +2210,9 @@ "php": ">=8.0.0" }, "require-dev": { + "laravel/pint": "^1.2", "phpmailer/phpmailer": "6.6.*", - "phpunit/phpunit": "9.5.*", - "squizlabs/php_codesniffer": "^3.6" + "phpunit/phpunit": "9.5.*" }, "type": "library", "autoload": { @@ -2237,12 +2224,6 @@ "license": [ "MIT" ], - "authors": [ - { - "name": "Jake Barnby", - "email": "jake@appwrite.io" - } - ], "description": "A simple, light and advanced PHP messaging library", "keywords": [ "library", @@ -2254,9 +2235,9 @@ ], "support": { "issues": "https://github.com/utopia-php/messaging/issues", - "source": "https://github.com/utopia-php/messaging/tree/0.1.0" + "source": "https://github.com/utopia-php/messaging/tree/0.1.1" }, - "time": "2022-09-29T11:22:48+00:00" + "time": "2023-02-07T05:42:46+00:00" }, { "name": "utopia-php/orchestration", @@ -4344,16 +4325,16 @@ }, { "name": "sebastian/environment", - "version": "5.1.4", + "version": "5.1.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7" + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", "shasum": "" }, "require": { @@ -4395,7 +4376,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4" + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" }, "funding": [ { @@ -4403,7 +4384,7 @@ "type": "github" } ], - "time": "2022-04-03T09:37:03+00:00" + "time": "2023-02-03T06:03:51+00:00" }, { "name": "sebastian/exporter", @@ -4717,16 +4698,16 @@ }, { "name": "sebastian/recursion-context", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", "shasum": "" }, "require": { @@ -4765,10 +4746,10 @@ } ], "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" }, "funding": [ { @@ -4776,7 +4757,7 @@ "type": "github" } ], - "time": "2020-10-26T13:17:30+00:00" + "time": "2023-02-03T06:07:39+00:00" }, { "name": "sebastian/resource-operations", @@ -4835,16 +4816,16 @@ }, { "name": "sebastian/type", - "version": "3.2.0", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e" + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", - "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", "shasum": "" }, "require": { @@ -4879,7 +4860,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.0" + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" }, "funding": [ { @@ -4887,7 +4868,7 @@ "type": "github" } ], - "time": "2022-09-12T14:47:03+00:00" + "time": "2023-02-03T06:13:03+00:00" }, { "name": "sebastian/version", @@ -5306,16 +5287,16 @@ }, { "name": "twig/twig", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "3ffcf4b7d890770466da3b2666f82ac054e7ec72" + "reference": "a6e0510cc793912b451fd40ab983a1d28f611c15" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/3ffcf4b7d890770466da3b2666f82ac054e7ec72", - "reference": "3ffcf4b7d890770466da3b2666f82ac054e7ec72", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/a6e0510cc793912b451fd40ab983a1d28f611c15", + "reference": "a6e0510cc793912b451fd40ab983a1d28f611c15", "shasum": "" }, "require": { @@ -5366,7 +5347,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.5.0" + "source": "https://github.com/twigphp/Twig/tree/v3.5.1" }, "funding": [ { @@ -5378,7 +5359,7 @@ "type": "tidelift" } ], - "time": "2022-12-27T12:28:18+00:00" + "time": "2023-02-08T07:49:20+00:00" } ], "aliases": [], diff --git a/docker-compose.yml b/docker-compose.yml index 780d79c475..97abe3eaaf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -659,7 +659,7 @@ services: hostname: exc1 <<: *x-logging stop_signal: SIGINT - image: meldiron/executor:v3 + image: meldiron/executor:0.3.0 networks: - appwrite - runtimes diff --git a/src/Appwrite/Event/Func.php b/src/Appwrite/Event/Func.php index 5f8b4c80c6..469c7eda29 100644 --- a/src/Appwrite/Event/Func.php +++ b/src/Appwrite/Event/Func.php @@ -10,7 +10,10 @@ class Func extends Event { protected string $jwt = ''; protected string $type = ''; - protected string $data = ''; + protected string $body = ''; + protected string $path = ''; + protected string $method = ''; + protected array $headers = []; protected ?Document $function = null; protected ?Document $execution = null; @@ -89,14 +92,53 @@ class Func extends Event } /** - * Sets custom data for the function event. + * Sets custom body for the function event. * - * @param string $data + * @param string $body * @return self */ - public function setData(string $data): self + public function setBody(string $body): self { - $this->data = $data; + $this->body = $body; + + return $this; + } + + /** + * Sets custom method for the function event. + * + * @param string $method + * @return self + */ + public function setMethod(string $method): self + { + $this->method = $method; + + return $this; + } + + /** + * Sets custom path for the function event. + * + * @param string $path + * @return self + */ + public function setPath(string $path): self + { + $this->path = $path; + + return $this; + } + + /** + * Sets custom headers for the function event. + * + * @param string $headers + * @return self + */ + public function setHeaders(array $headers): self + { + $this->headers = $headers; return $this; } @@ -155,7 +197,10 @@ class Func extends Event 'jwt' => $this->jwt, 'payload' => $this->payload, 'events' => $events, - 'data' => $this->data, + 'body' => $this->body, + 'path' => $this->path, + 'headers' => $this->headers, + 'method' => $this->method, ]); } diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 092f8eb230..a7d1bf4555 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -61,6 +61,7 @@ use Appwrite\Utopia\Response\Model\Platform; use Appwrite\Utopia\Response\Model\Project; use Appwrite\Utopia\Response\Model\Rule; use Appwrite\Utopia\Response\Model\Deployment; +use Appwrite\Utopia\Response\Model\Headers; use Appwrite\Utopia\Response\Model\Token; use Appwrite\Utopia\Response\Model\Webhook; use Appwrite\Utopia\Response\Model\Preferences; @@ -187,6 +188,7 @@ class Response extends SwooleResponse public const MODEL_BUILD = 'build'; public const MODEL_BUILD_LIST = 'buildList'; // Not used anywhere yet public const MODEL_FUNC_PERMISSIONS = 'funcPermissions'; + public const MODEL_HEADERS = 'headers'; // Project public const MODEL_PROJECT = 'project'; @@ -341,6 +343,7 @@ class Response extends SwooleResponse ->setModel(new UsageFunctions()) ->setModel(new UsageFunction()) ->setModel(new UsageProject()) + ->setModel(new Headers()) // Verification // Recovery // Tests (keep last) diff --git a/src/Appwrite/Utopia/Response/Model/Execution.php b/src/Appwrite/Utopia/Response/Model/Execution.php index 13011a24b7..223000385f 100644 --- a/src/Appwrite/Utopia/Response/Model/Execution.php +++ b/src/Appwrite/Utopia/Response/Model/Execution.php @@ -60,19 +60,25 @@ class Execution extends Model 'default' => 0, 'example' => 0, ]) - ->addRule('response', [ + ->addRule('body', [ 'type' => self::TYPE_STRING, 'description' => 'The script response output string. Logs the last 4,000 characters of the execution response output.', 'default' => '', 'example' => '', ]) - ->addRule('stdout', [ + ->addRule('headers', [ + 'type' => Response::MODEL_HEADERS, + 'description' => 'Response headers as a key-value object', + 'default' => new \stdClass(), + 'example' => ['x-internal-timezone' => 'UTC'], + ]) + ->addRule('logs', [ 'type' => self::TYPE_STRING, 'description' => 'The script stdout output string. Logs the last 4,000 characters of the execution stdout output. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.', 'default' => '', 'example' => '', ]) - ->addRule('stderr', [ + ->addRule('errors', [ 'type' => self::TYPE_STRING, 'description' => 'The script stderr output string. Logs the last 4,000 characters of the execution stderr output. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.', 'default' => '', diff --git a/src/Appwrite/Utopia/Response/Model/Headers.php b/src/Appwrite/Utopia/Response/Model/Headers.php new file mode 100644 index 0000000000..5cfc9e8891 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/Headers.php @@ -0,0 +1,28 @@ + $runtimeId ]; + $reqHeaders = [ 'x-opr-runtime-id' => $runtimeId ]; $params = [ 'runtimeId' => $runtimeId, 'source' => $source, @@ -92,7 +92,7 @@ class Executor $timeout = (int) App::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900); - $response = $this->call(self::METHOD_POST, $route, $headers, $params, true, $timeout); + $response = $this->call(self::METHOD_POST, $route, $reqHeaders, $params, true, $timeout); $status = $response['headers']['status-code']; if ($status >= 400) { @@ -120,22 +120,28 @@ class Executor public function createExecution( string $projectId, string $deploymentId, - string $payload, + string $body, array $variables, int $timeout, string $image, string $source, string $entrypoint, - string $version + string $version, + string $path, + string $method, + array $headers, ) { $runtimeId = "$projectId-$deploymentId"; $route = '/runtimes/' . $runtimeId . '/execution'; - $headers = [ 'x-opr-runtime-id' => $runtimeId ]; + $reqHeaders = [ 'x-opr-runtime-id' => $runtimeId ]; $params = [ 'runtimeId' => $runtimeId, 'variables' => $variables, - 'payload' => $payload, + 'body' => $body, 'timeout' => $timeout, + 'path' => $path, + 'method' => $method, + 'headers' => $headers, 'image' => $image, 'source' => $source, @@ -147,7 +153,7 @@ class Executor $timeout = (int) App::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900); - $response = $this->call(self::METHOD_POST, $route, $headers, $params, true, $timeout); + $response = $this->call(self::METHOD_POST, $route, $reqHeaders, $params, true, $timeout); $status = $response['headers']['status-code']; if ($status >= 400) { diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index 56b72e4468..8416b5d804 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -590,8 +590,8 @@ class FunctionsCustomClientTest extends Scope $this->assertNotEmpty($output['APPWRITE_FUNCTION_JWT']); $this->assertEquals($projectId, $output['APPWRITE_FUNCTION_PROJECT_ID']); // Client should never see logs and errors - $this->assertEmpty($execution['body']['stdout']); - $this->assertEmpty($execution['body']['stderr']); + $this->assertEmpty($execution['body']['logs']); + $this->assertEmpty($execution['body']['errors']); // Cleanup : Delete function $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index e2d7b8482b..2eea5268ed 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -611,7 +611,8 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals('waiting', $execution['body']['status']); $this->assertEquals(0, $execution['body']['statusCode']); $this->assertEquals('', $execution['body']['response']); - $this->assertEquals('', $execution['body']['stderr']); + $this->assertEquals('', $execution['body']['errors']); + $this->assertEquals('', $execution['body']['logs']); $this->assertEquals(0, $execution['body']['duration']); sleep(10); @@ -634,7 +635,8 @@ class FunctionsCustomServerTest extends Scope $this->assertStringContainsString('PHP', $execution['body']['response']); $this->assertStringContainsString('8.0', $execution['body']['response']); $this->assertStringContainsString('êä', $execution['body']['response']); // tests unknown utf-8 chars - $this->assertEquals('', $execution['body']['stderr']); + $this->assertEquals('', $execution['body']['errors']); + $this->assertEquals('', $execution['body']['logs']); $this->assertLessThan(1.500, $execution['body']['duration']); /** @@ -917,7 +919,8 @@ class FunctionsCustomServerTest extends Scope $this->assertLessThan(6, $executions['body']['executions'][0]['duration']); $this->assertGreaterThan(4, $executions['body']['executions'][0]['duration']); $this->assertEquals($executions['body']['executions'][0]['response'], ''); - $this->assertEquals($executions['body']['executions'][0]['stderr'], 'An internal curl error has occurred within the executor! Error Msg: Operation timed out'); + $this->assertEquals($executions['body']['executions'][0]['logs'], ''); + $this->assertEquals($executions['body']['executions'][0]['errors'], 'An internal curl error has occurred within the executor! Error Msg: Operation timed out'); // Cleanup : Delete function $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [