From dd2a04b36228c5dbe70c9dbe18e8e76e8e407542 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Mon, 28 Jul 2025 10:58:36 +0530 Subject: [PATCH] Add headers for sync executions --- app/controllers/general.php | 8 ++-- .../Functions/Http/Executions/Create.php | 6 +++ .../Functions/FunctionsCustomServerTest.php | 42 ++++++++++++++++++- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index ad6b61d6b8..446ffd9058 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -57,7 +57,6 @@ Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE); function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) { - // add headers here as well $host = $request->getHostname() ?? ''; if (!empty($previewHostname)) { $host = $previewHostname; @@ -371,8 +370,11 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $headers['x-appwrite-key'] = API_KEY_DYNAMIC . '_' . $jwtKey; $headers['x-appwrite-trigger'] = 'http'; $headers['x-appwrite-user-jwt'] = ''; - // add here - // in API - for sync executions, hard code delay to 0 + // add headers for sync executions + $currentTime = new \DateTime(); + $headers['x-appwrite-scheduled-at'] = $currentTime->format('Y-m-d\TH:i:s.v\Z'); + $headers['x-appwrite-executed-at'] = $currentTime->format('Y-m-d\TH:i:s.v\Z'); + $headers['x-appwrite-execution-delay'] = '0'; $ip = $headers['x-real-ip'] ?? ''; if (!empty($ip)) { diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php index b5af34823a..ad1e711ab7 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -231,6 +231,12 @@ class Create extends Base $currentTime = new \DateTime(); $headers['x-appwrite-scheduled-at'] = $currentTime->format('Y-m-d\TH:i:s.v\Z'); + if (!$async) { + $executedAt = new \DateTime(); + $headers['x-appwrite-executed-at'] = $executedAt->format('Y-m-d\TH:i:s.v\Z'); + $headers['x-appwrite-execution-delay'] = '0'; + } + $ip = $headers['x-real-ip'] ?? ''; if (!empty($ip)) { $record = $geodb->get($ip); diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index eec0d6a236..365be656c7 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -2294,7 +2294,7 @@ class FunctionsCustomServerTest extends Scope $this->cleanupFunction($functionId); } - public function testExecutionHeaders() + public function testAsyncExecutionHeaders() { $functionId = $this->setupFunction([ 'functionId' => ID::unique(), @@ -2343,4 +2343,44 @@ class FunctionsCustomServerTest extends Scope $this->cleanupFunction($functionId); } + + public function testSyncExecutionHeaders() + { + $functionId = $this->setupFunction([ + 'functionId' => ID::unique(), + 'name' => 'Test sync execution headers', + 'execute' => [Role::any()->toString()], + 'runtime' => 'node-22', + 'entrypoint' => 'index.js', + 'timeout' => 10, + ]); + + $deploymentId = $this->setupDeployment($functionId, [ + 'code' => $this->packageFunction('basic'), + 'activate' => true, + ]); + + $deployment = $this->getDeployment($functionId, $deploymentId); + $this->assertEquals(200, $deployment['headers']['status-code']); + + $execution = $this->createExecution($functionId, [ + 'async' => false, + ]); + + $this->assertEquals(201, $execution['headers']['status-code']); + $this->assertEquals('completed', $execution['body']['status']); + $this->assertEquals(200, $execution['body']['responseStatusCode']); + $this->assertGreaterThan(0, $execution['body']['duration']); + $this->assertNotEmpty($execution['body']['logs']); + $this->assertNotEmpty($execution['body']['responseHeaders']); + + $requestHeaders = array_column($execution['body']['requestHeaders'], 'value', 'name'); + $this->assertArrayHasKey('x-appwrite-scheduled-at', $requestHeaders); + $this->assertArrayHasKey('x-appwrite-executed-at', $requestHeaders); + $this->assertArrayHasKey('x-appwrite-execution-delay', $requestHeaders); + $this->assertEquals('0', $requestHeaders['x-appwrite-execution-delay']); + $this->assertGreaterThanOrEqual($requestHeaders['x-appwrite-scheduled-at'], $requestHeaders['x-appwrite-executed-at']); + + $this->cleanupFunction($functionId); + } }