From 8df305576c731d8ceee49e2a0db2fe57b452f983 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Tue, 26 Aug 2025 18:34:43 +0530 Subject: [PATCH 1/3] Add execution id and log id to response headers --- app/controllers/general.php | 6 ++++++ app/init/constants.php | 2 +- .../Modules/Functions/Http/Executions/Create.php | 2 ++ src/Appwrite/Platform/Workers/Functions.php | 1 + .../Functions/FunctionsCustomClientTest.php | 13 +++++++++++++ .../Functions/FunctionsCustomServerTest.php | 13 +++++++++++++ tests/e2e/Services/Sites/SitesCustomServerTest.php | 3 +++ 7 files changed, 39 insertions(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index a4f89d14c7..cc812edc2d 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -610,6 +610,12 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } } + if ($deployment->getAttribute('resourceType') === 'functions') { + $executionResponse['headers']['x-appwrite-execution-id'] = $execution->getId(); + } elseif ($deployment->getAttribute('resourceType') === 'sites') { + $executionResponse['headers']['x-appwrite-log-id'] = $execution->getId(); + } + $headersFiltered = []; foreach ($executionResponse['headers'] as $key => $value) { if (\in_array(\strtolower($key), FUNCTION_ALLOWLIST_HEADERS_RESPONSE)) { diff --git a/app/init/constants.php b/app/init/constants.php index c2d529191b..95c99ba7ea 100644 --- a/app/init/constants.php +++ b/app/init/constants.php @@ -147,7 +147,7 @@ const APP_FUNCTION_LOG_LENGTH_LIMIT = 1000000; const APP_FUNCTION_ERROR_LENGTH_LIMIT = 1000000; // Function headers const FUNCTION_ALLOWLIST_HEADERS_REQUEST = ['content-type', 'agent', 'content-length', 'host']; -const FUNCTION_ALLOWLIST_HEADERS_RESPONSE = ['content-type', 'content-length']; +const FUNCTION_ALLOWLIST_HEADERS_RESPONSE = ['content-type', 'content-length', 'x-appwrite-execution-id', 'x-appwrite-log-id']; // Message types const MESSAGE_TYPE_EMAIL = 'email'; const MESSAGE_TYPE_SMS = 'sms'; diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php index 64056b7db7..c54b1d7303 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -486,6 +486,8 @@ class Create extends Base $headers[] = ['name' => $key, 'value' => $value]; } + $headers[] = ['name' => 'x-appwrite-execution-id', 'value' => $execution->getId()]; + $execution->setAttribute('responseBody', $executionResponse['body'] ?? ''); $execution->setAttribute('responseHeaders', $headers); diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index 864d6451b8..295c02061f 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -549,6 +549,7 @@ class Functions extends Action $headersFiltered[] = [ 'name' => $key, 'value' => $value ]; } } + $headersFiltered[] = ['name' => 'x-appwrite-execution-id', 'value' => $execution->getId()]; $maxLogLength = APP_FUNCTION_LOG_LENGTH_LIMIT; $logs = $executionResponse['logs'] ?? ''; diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index a60c9e59cf..0907e3da0b 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -142,6 +142,19 @@ class FunctionsCustomClientTest extends Scope ]); $output = json_decode($execution['body']['responseBody'], true); $this->assertEquals(201, $execution['headers']['status-code']); + + $this->assertNotEmpty($execution['body']['responseHeaders']); + + $executionIdHeader = null; + foreach ($execution['body']['responseHeaders'] as $header) { + if ($header['name'] === 'x-appwrite-execution-id') { + $executionIdHeader = $header['value']; + break; + } + } + $this->assertNotEmpty($executionIdHeader); + $this->assertEquals($execution['body']['$id'], $executionIdHeader); + $this->assertEquals(200, $execution['body']['responseStatusCode']); $this->assertGreaterThan(0, $execution['body']['duration']); $this->assertEquals('completed', $execution['body']['status']); diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index 1d993c19b7..ad14990c2b 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -892,6 +892,19 @@ class FunctionsCustomServerTest extends Scope ]); $this->assertEquals(201, $execution['headers']['status-code']); + + $this->assertNotEmpty($execution['body']['responseHeaders']); + + $executionIdHeader = null; + foreach ($execution['body']['responseHeaders'] as $header) { + if ($header['name'] === 'x-appwrite-execution-id') { + $executionIdHeader = $header['value']; + break; + } + } + $this->assertNotEmpty($executionIdHeader); + $this->assertEquals($execution['body']['$id'], $executionIdHeader); + $this->assertNotEmpty($execution['body']['$id']); $this->assertNotEmpty($execution['body']['functionId']); $this->assertEquals(true, (new DatetimeValidator())->isValid($execution['body']['$createdAt'])); diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index 0e792d6c36..ac1aab21ce 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -1433,6 +1433,9 @@ class SitesCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertStringContainsString("Index page", $response['body']); + $this->assertArrayHasKey('x-appwrite-log-id', $response['headers']); + $this->assertNotEmpty($response['headers']['x-appwrite-log-id']); + $response = $proxyClient->call(Client::METHOD_GET, '/contact', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], From f61189355894fb81c4c05ee37a60dca9aff1fc0a Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Tue, 26 Aug 2025 18:40:18 +0530 Subject: [PATCH 2/3] Remove execution headers from allowlist --- app/init/constants.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/init/constants.php b/app/init/constants.php index 95c99ba7ea..c2d529191b 100644 --- a/app/init/constants.php +++ b/app/init/constants.php @@ -147,7 +147,7 @@ const APP_FUNCTION_LOG_LENGTH_LIMIT = 1000000; const APP_FUNCTION_ERROR_LENGTH_LIMIT = 1000000; // Function headers const FUNCTION_ALLOWLIST_HEADERS_REQUEST = ['content-type', 'agent', 'content-length', 'host']; -const FUNCTION_ALLOWLIST_HEADERS_RESPONSE = ['content-type', 'content-length', 'x-appwrite-execution-id', 'x-appwrite-log-id']; +const FUNCTION_ALLOWLIST_HEADERS_RESPONSE = ['content-type', 'content-length']; // Message types const MESSAGE_TYPE_EMAIL = 'email'; const MESSAGE_TYPE_SMS = 'sms'; From aac98b2ec7316cea35b34d2eb6c84a944afc9ffb Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Tue, 26 Aug 2025 18:56:26 +0530 Subject: [PATCH 3/3] Update function domain test --- .../Platform/Modules/Functions/Http/Executions/Create.php | 4 ++-- src/Appwrite/Platform/Workers/Functions.php | 3 ++- tests/e2e/Services/Functions/FunctionsCustomServerTest.php | 3 +++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php index c54b1d7303..3967b20e49 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -481,13 +481,13 @@ class Create extends Base $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); } + $executionResponse['headers']['x-appwrite-execution-id'] = $execution->getId(); + $headers = []; foreach (($executionResponse['headers'] ?? []) as $key => $value) { $headers[] = ['name' => $key, 'value' => $value]; } - $headers[] = ['name' => 'x-appwrite-execution-id', 'value' => $execution->getId()]; - $execution->setAttribute('responseBody', $executionResponse['body'] ?? ''); $execution->setAttribute('responseHeaders', $headers); diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index 295c02061f..af91019f2e 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -543,13 +543,14 @@ class Functions extends Action $status = $executionResponse['statusCode'] >= 500 ? 'failed' : 'completed'; + $executionResponse['headers']['x-appwrite-execution-id'] = $execution->getId(); + $headersFiltered = []; foreach ($executionResponse['headers'] as $key => $value) { if (\in_array(\strtolower($key), FUNCTION_ALLOWLIST_HEADERS_RESPONSE)) { $headersFiltered[] = [ 'name' => $key, 'value' => $value ]; } } - $headersFiltered[] = ['name' => 'x-appwrite-execution-id', 'value' => $execution->getId()]; $maxLogLength = APP_FUNCTION_LOG_LENGTH_LIMIT; $logs = $executionResponse['logs'] ?? ''; diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index ad14990c2b..95781f0390 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -1689,6 +1689,9 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals($cookie, $response['body']); + $this->assertArrayHasKey('x-appwrite-execution-id', $response['headers']); + $this->assertNotEmpty($response['headers']['x-appwrite-execution-id']); + // Async execution document creation $this->assertEventually(function () use ($functionId) { $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', array_merge([