From 2e177873c07c5638b262c775f4d3e463ee7ff209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Sat, 29 Jul 2023 18:20:20 +0200 Subject: [PATCH] Update execution response model --- app/config/collections.php | 85 +++++++++++-------- app/controllers/api/functions.php | 64 +++++++------- app/workers/functions.php | 41 ++++----- .../Database/Validator/Queries/Executions.php | 2 +- .../Utopia/Response/Model/Execution.php | 24 +++--- 5 files changed, 113 insertions(+), 103 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index a2c2693a9e..24588fc663 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -3540,39 +3540,6 @@ $collections = [ 'default' => null, 'filters' => [], ], - [ - 'array' => false, - '$id' => ID::custom('method'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('path'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('agent'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], [ '$id' => ID::custom('status'), 'type' => Database::VAR_STRING, @@ -3584,6 +3551,17 @@ $collections = [ 'array' => false, 'filters' => [], ], + [ + '$id' => ID::custom('duration'), + 'type' => Database::VAR_FLOAT, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], [ '$id' => ID::custom('errors'), 'type' => Database::VAR_STRING, @@ -3607,7 +3585,40 @@ $collections = [ 'filters' => [], ], [ - '$id' => ID::custom('statusCode'), + 'array' => false, + '$id' => ID::custom('requestMethod'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('requestPath'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + '$id' => ID::custom('requestHeaders'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('responseStatusCode'), 'type' => Database::VAR_INTEGER, 'format' => '', 'size' => 0, @@ -3618,10 +3629,10 @@ $collections = [ 'filters' => [], ], [ - '$id' => ID::custom('duration'), - 'type' => Database::VAR_FLOAT, + '$id' => ID::custom('responseHeaders'), + 'type' => Database::VAR_STRING, 'format' => '', - 'size' => 0, + 'size' => 16384, 'signed' => true, 'required' => false, 'default' => null, diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 2debe19af2..9276a0b2e7 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -1389,34 +1389,6 @@ App::post('/v1/functions/:functionId/executions') throw new Exception(Exception::USER_UNAUTHORIZED, $validator->getDescription()); } - $executionId = ID::unique(); - - $agent = ''; - foreach ($headers as $header => $value) { - if (\strtolower($header) === 'user-agent') { - $agent = $value; - } - } - - $execution = new Document([ - '$id' => $executionId, - '$permissions' => !$user->isEmpty() ? [Permission::read(Role::user($user->getId()))] : [], - 'functionInternalId' => $function->getInternalId(), - 'functionId' => $function->getId(), - 'deploymentInternalId' => $deployment->getInternalId(), - 'deploymentId' => $deployment->getId(), - 'trigger' => 'http', // http / schedule / event - 'status' => $async ? 'waiting' : 'processing', // waiting / processing / completed / failed - 'statusCode' => 0, - 'errors' => '', - 'logs' => '', - 'duration' => 0.0, - 'search' => implode(' ', [$functionId, $executionId]), - 'path' => $path, - 'method' => $method, - 'agent' => $agent - ]); - $jwt = ''; // initialize if (!$user->isEmpty()) { // If userId exists, generate a JWT for function $sessions = $user->getAttribute('sessions', []); @@ -1441,7 +1413,6 @@ App::post('/v1/functions/:functionId/executions') $headers['x-appwrite-trigger'] = 'http'; $headers['x-appwrite-user-id'] = $user->getId() ?? ''; $headers['x-appwrite-user-jwt'] = $jwt ?? ''; - $headers['x-appwrite-country-code'] = ''; $headers['x-appwrite-continent-code'] = ''; $headers['x-appwrite-continent-eu'] = 'false'; @@ -1459,6 +1430,30 @@ App::post('/v1/functions/:functionId/executions') } } + // TODO: Filter headers + + $executionId = ID::unique(); + + $execution = new Document([ + '$id' => $executionId, + '$permissions' => !$user->isEmpty() ? [Permission::read(Role::user($user->getId()))] : [], + 'functionInternalId' => $function->getInternalId(), + 'functionId' => $function->getId(), + 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentId' => $deployment->getId(), + 'trigger' => 'http', // http / schedule / event + 'status' => $async ? 'waiting' : 'processing', // waiting / processing / completed / failed + 'responseStatusCode' => 0, + 'responseHeaders' => [], + 'requestPath' => $path, + 'requestMethod' => $method, + 'requestHeaders' => $headers, + 'errors' => '', + 'logs' => '', + 'duration' => 0.0, + 'search' => implode(' ', [$functionId, $executionId]), + ]); + $events ->setParam('functionId', $function->getId()) ->setParam('executionId', $execution->getId()) @@ -1535,10 +1530,13 @@ App::post('/v1/functions/:functionId/executions') runtimeEntrypoint: 'cp /tmp/code.tar.gz /mnt/code/code.tar.gz && nohup helpers/start.sh "' . $command . '"' ); + // TODO: Filter headers + /** Update execution status */ $status = $executionResponse['statusCode'] >= 400 ? 'failed' : 'completed'; $execution->setAttribute('status', $status); - $execution->setAttribute('statusCode', $executionResponse['statusCode']); + $execution->setAttribute('responseStatusCode', $executionResponse['statusCode']); + $execution->setAttribute('responseHeaders', $executionResponse['headers']); $execution->setAttribute('logs', $executionResponse['logs']); $execution->setAttribute('errors', $executionResponse['errors']); $execution->setAttribute('duration', $executionResponse['duration']); @@ -1548,7 +1546,7 @@ App::post('/v1/functions/:functionId/executions') $execution ->setAttribute('duration', $durationEnd - $durationStart) ->setAttribute('status', 'failed') - ->setAttribute('statusCode', 500) + ->setAttribute('responseStatusCode', 500) ->setAttribute('errors', $th->getMessage() . '\nError Code: ' . $th->getCode()); Console::error($th->getMessage()); } @@ -1574,8 +1572,8 @@ App::post('/v1/functions/:functionId/executions') $execution->setAttribute('errors', ''); } - $execution->setAttribute('body', $executionResponse['body']); - $execution->setAttribute('headers', $executionResponse['headers']); + $execution->setAttribute('responseBody', $executionResponse['body']); + $execution->setAttribute('responseHeaders', $executionResponse['headers']); $response ->setStatusCode(Response::STATUS_CODE_CREATED) diff --git a/app/workers/functions.php b/app/workers/functions.php index a942a8888f..99a54c2b00 100644 --- a/app/workers/functions.php +++ b/app/workers/functions.php @@ -78,32 +78,35 @@ Server::setResource('execute', function () { $runtime = $runtimes[$function->getAttribute('runtime')]; + $headers['x-appwrite-trigger'] = $trigger; + $headers['x-appwrite-event'] = $event ?? ''; + $headers['x-appwrite-user-id'] = $user->getId() ?? ''; + $headers['x-appwrite-user-jwt'] = $jwt ?? ''; + /** Create execution or update execution status */ $execution = $dbForProject->getDocument('executions', $executionId ?? ''); if ($execution->isEmpty()) { - $agent = ''; - foreach ($headers as $header => $value) { - if (\strtolower($header) === 'user-agent') { - $agent = $value; - } - } + // TODO: Filter headers $executionId = ID::unique(); $execution = new Document([ '$id' => $executionId, '$permissions' => $user->isEmpty() ? [] : [Permission::read(Role::user($user->getId()))], - 'functionId' => $functionId, - 'deploymentId' => $deploymentId, - 'trigger' => $trigger, + 'functionInternalId' => $function->getInternalId(), + 'functionId' => $function->getId(), + 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentId' => $deployment->getId(), + 'trigger' => 'http', 'status' => 'processing', - 'statusCode' => 0, + 'responseStatusCode' => 0, + 'responseHeaders' => [], + 'requestPath' => $path, + 'requestMethod' => $method, + 'requestHeaders' => $headers, 'errors' => '', 'logs' => '', 'duration' => 0.0, 'search' => implode(' ', [$functionId, $executionId]), - 'path' => $path, - 'method' => $method, - 'agent' => $agent ]); if ($function->getAttribute('logging')) { @@ -152,11 +155,6 @@ Server::setResource('execute', function () { 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'] ?? '', ]); - $headers['x-appwrite-trigger'] = $trigger; - $headers['x-appwrite-event'] = $event ?? ''; - $headers['x-appwrite-user-id'] = $user->getId() ?? ''; - $headers['x-appwrite-user-jwt'] = $jwt ?? ''; - $body = $eventData ?? ''; if (empty($body)) { $body = $data ?? ''; @@ -184,10 +182,13 @@ Server::setResource('execute', function () { $status = $executionResponse['statusCode'] >= 400 ? 'failed' : 'completed'; + // TODO: Filter headers + /** Update execution status */ $execution ->setAttribute('status', $status) - ->setAttribute('statusCode', $executionResponse['statusCode']) + ->setAttribute('responseStatusCode', $executionResponse['statusCode']) + ->setAttribute('responseHeaders', $executionResponse['headers']) ->setAttribute('logs', $executionResponse['logs']) ->setAttribute('errors', $executionResponse['errors']) ->setAttribute('duration', $executionResponse['duration']); @@ -197,7 +198,7 @@ Server::setResource('execute', function () { $execution ->setAttribute('duration', $durationEnd - $durationStart) ->setAttribute('status', 'failed') - ->setAttribute('statusCode', 500) + ->setAttribute('responseStatusCode', 500) ->setAttribute('errors', $th->getMessage() . '\nError Code: ' . $th->getCode()); Console::error($th->getTraceAsString()); diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php b/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php index 2bfe46e28d..ecceab7fae 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php @@ -7,7 +7,7 @@ class Executions extends Base public const ALLOWED_ATTRIBUTES = [ 'trigger', 'status', - 'statusCode', + 'responseStatusCode', 'duration' ]; diff --git a/src/Appwrite/Utopia/Response/Model/Execution.php b/src/Appwrite/Utopia/Response/Model/Execution.php index d590d0f145..1d156b029d 100644 --- a/src/Appwrite/Utopia/Response/Model/Execution.php +++ b/src/Appwrite/Utopia/Response/Model/Execution.php @@ -54,39 +54,39 @@ class Execution extends Model 'default' => '', 'example' => 'processing', ]) - ->addRule('agent', [ - 'type' => self::TYPE_STRING, - 'description' => 'HTTP request user agent header.', - 'default' => '', - 'example' => 'Chrome/51.0.2704.103', - ]) - ->addRule('method', [ + ->addRule('requestMethod', [ 'type' => self::TYPE_STRING, 'description' => 'HTTP request method type.', 'default' => '', 'example' => 'GET', ]) - ->addRule('path', [ + ->addRule('requestPath', [ 'type' => self::TYPE_STRING, 'description' => 'HTTP request path and query.', 'default' => '', 'example' => '/articles?id=5', ]) - ->addRule('statusCode', [ + ->addRule('requestHeaders', [ + 'type' => Response::MODEL_HEADERS, + 'description' => 'HTTP request headers as a key-value object. This will return only whitelisted headers.', + 'default' => new \stdClass(), + 'example' => ['x-internal-timezone' => 'UTC'], + ]) + ->addRule('responseStatusCode', [ 'type' => self::TYPE_INTEGER, 'description' => 'HTTP response status code.', 'default' => 0, 'example' => 200, ]) - ->addRule('body', [ + ->addRule('responseBody', [ 'type' => self::TYPE_STRING, 'description' => 'HTTP response body. This will return empty unless execution is created as synchronous.', 'default' => '', 'example' => 'Developers are awesome.', ]) - ->addRule('headers', [ + ->addRule('responseheaders', [ 'type' => Response::MODEL_HEADERS, - 'description' => 'HTTP response headers as a key-value object. This will return empty unless execution is created as synchronous.', + 'description' => 'HTTP response headers as a key-value object. This will return only whitelisted headers. All headers are returned if execution is created as synchronous.', 'default' => new \stdClass(), 'example' => ['x-internal-timezone' => 'UTC'], ])