diff --git a/docker-compose.yml b/docker-compose.yml index 9b5e7a1fd7..7b201f4ac4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -963,7 +963,7 @@ services: hostname: exc1 <<: *x-logging stop_signal: SIGINT - image: openruntimes/executor:0.7.22 + image: openruntimes/executor:0.8.1 restart: unless-stopped networks: - appwrite diff --git a/tests/e2e/Client.php b/tests/e2e/Client.php index 278d1cd0d5..e411b68454 100644 --- a/tests/e2e/Client.php +++ b/tests/e2e/Client.php @@ -216,7 +216,15 @@ class Client return $len; }); - if ($method != self::METHOD_GET) { + + if ($method === self::METHOD_HEAD) { + curl_setopt($ch, CURLOPT_NOBODY, true); // This is crucial for HEAD requests + curl_setopt($ch, CURLOPT_HEADER, false); + } else { + curl_setopt($ch, CURLOPT_NOBODY, false); + } + + if ($method != self::METHOD_GET && $method != self::METHOD_HEAD) { curl_setopt($ch, CURLOPT_POSTFIELDS, $query); } @@ -229,7 +237,7 @@ class Client $responseType = $responseHeaders['content-type'] ?? ''; $responseStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE); - if ($decode) { + if ($decode && $method !== self::METHOD_HEAD) { $strpos = strpos($responseType, ';'); $strpos = \is_bool($strpos) ? \strlen($responseType) : $strpos; switch (substr($responseType, 0, $strpos)) { @@ -255,6 +263,9 @@ class Client $json = null; break; } + } elseif ($method === self::METHOD_HEAD) { + // For HEAD requests, always set body to empty string regardless of decode flag + $responseBody = ''; } if ((curl_errno($ch)/* || 200 != $responseStatus*/)) { diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index ccabc2a79e..a60c9e59cf 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -74,6 +74,50 @@ class FunctionsCustomClientTest extends Scope $this->cleanupFunction($functionId); } + public function testCreateHeadExecution() + { + /** + * Test for SUCCESS + */ + $functionId = $this->setupFunction([ + 'functionId' => ID::unique(), + 'name' => 'Test', + 'execute' => [Role::user($this->getUser()['$id'])->toString()], + 'runtime' => 'node-22', + 'entrypoint' => 'index.js', + 'events' => [ + 'users.*.create', + 'users.*.delete', + ], + 'timeout' => 10, + ]); + $this->setupDeployment($functionId, [ + 'code' => $this->packageFunction('basic'), + 'activate' => true + ]); + + // Deny create async execution as guest + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], [ + 'async' => true, + ]); + $this->assertEquals(401, $execution['headers']['status-code']); + + // Allow create async execution as user + $execution = $this->client->call(Client::METHOD_HEAD, '/functions/' . $functionId . '/executions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'async' => true, + ]); + $this->assertEquals(200, $execution['headers']['status-code']); + $this->assertEmpty($execution['body']); + + $this->cleanupFunction($functionId); + } + public function testCreateCustomExecution(): array { /**