Skip to content

Commit ec12e3d

Browse files
authored
Merge pull request #179 from open-runtimes/add-head-request-support
chore: allow head method requests in /executions
2 parents 7c93e61 + 6445f4d commit ec12e3d

File tree

5 files changed

+38
-5
lines changed

5 files changed

+38
-5
lines changed

.github/workflows/tests.yml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,16 @@ jobs:
2929
3030
- name: Run Tests
3131
run: |
32-
docker run --rm -v $PWD:/app -v /tmp:/tmp -v /var/run/docker.sock:/var/run/docker.sock --network executor_runtimes -w /app phpswoole/swoole:5.1.2-php8.3-alpine sh -c "apk update && apk add docker-cli zip unzip && composer install --profile --ignore-platform-reqs && composer test"
32+
docker run --rm \
33+
-v $PWD:/app \
34+
-v /tmp:/tmp \
35+
-v /var/run/docker.sock:/var/run/docker.sock \
36+
--network executor_runtimes \
37+
-w /app \
38+
phpswoole/swoole:5.1.2-php8.3-alpine \
39+
sh -c "
40+
apk update && \
41+
apk add docker-cli zip unzip && \
42+
composer install --profile --ignore-platform-reqs && \
43+
composer test
44+
"

app/controllers.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@
150150
->param('runtimeId', '', new Text(64), 'The runtimeID to execute.')
151151
->param('body', '', new Text(20971520), 'Data to be forwarded to the function, this is user specified.', true)
152152
->param('path', '/', new Text(2048), 'Path from which execution comes.', true)
153-
->param('method', 'GET', new Whitelist(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], true), 'Path from which execution comes.', true)
153+
->param('method', 'GET', new Whitelist(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'], true), 'Path from which execution comes.', true)
154154
->param('headers', [], new AnyOf([new Text(65535), new Assoc()], AnyOf::TYPE_MIXED), 'Headers passed into runtime.', true)
155155
->param('timeout', 15, new Integer(true), 'Function maximum execution time in seconds.', true)
156156
// Runtime-related

src/Executor/Runner/Docker.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1148,7 +1148,10 @@ public function createExecution(
11481148
} while ((++$attempts < $retryAttempts) || (\microtime(true) - $startTime < $timeout));
11491149

11501150
// Error occurred
1151-
if ($executionResponse['errNo'] !== CURLE_OK) {
1151+
if (
1152+
$executionResponse['errNo'] !== CURLE_OK &&
1153+
$executionResponse['errNo'] !== CURLE_PARTIAL_FILE // Head request may return partial file
1154+
) {
11521155
$log->addExtra('activeRuntime', $this->activeRuntimes->get($runtimeName));
11531156
$log->addExtra('error', $executionResponse['error']);
11541157
$log->addTag('hostname', $hostname);

tests/Client.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,14 @@ public function call(string $method, string $path = '', array $headers = [], arr
131131
return $len;
132132
});
133133

134-
if ($method != self::METHOD_GET) {
134+
if ($method === self::METHOD_HEAD) {
135+
curl_setopt($ch, CURLOPT_NOBODY, true); // This is crucial for HEAD requests
136+
curl_setopt($ch, CURLOPT_HEADER, false);
137+
} else {
138+
curl_setopt($ch, CURLOPT_NOBODY, false);
139+
}
140+
141+
if ($method != self::METHOD_GET && $method != self::METHOD_HEAD) {
135142
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
136143
}
137144

@@ -151,7 +158,7 @@ public function call(string $method, string $path = '', array $headers = [], arr
151158
$responseType = $responseHeaders['content-type'] ?? '';
152159
$responseStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
153160

154-
if ($decode) {
161+
if ($decode && $method !== self::METHOD_HEAD) {
155162
$strpos = strpos($responseType, ';');
156163
$strpos = \is_bool($strpos) ? \strlen($responseType) : $strpos;
157164
switch (substr($responseType, 0, $strpos)) {
@@ -177,6 +184,9 @@ public function call(string $method, string $path = '', array $headers = [], arr
177184
$json = null;
178185
break;
179186
}
187+
} elseif ($method === self::METHOD_HEAD) {
188+
// For HEAD requests, always set body to empty string regardless of decode flag
189+
$responseBody = '';
180190
}
181191

182192
if ((curl_errno($ch)/* || 200 != $responseStatus*/)) {

tests/ExecutorTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,14 @@ public function testExecute(): void
547547
$this->assertEquals(200, $response['headers']['status-code']);
548548
$this->assertStringStartsWith('multipart/form-data', $response['headers']['content-type']);
549549

550+
/** Execute HEAD request */
551+
$response = $this->client->call(Client::METHOD_HEAD, '/runtimes/test-exec-coldstart/executions');
552+
553+
$this->assertEquals(404, $response['headers']['status-code']); // not found
554+
// For HEAD requests, the body should be empty but headers should be present
555+
$this->assertEmpty($response['body']);
556+
$this->assertArrayHasKey('content-type', $response['headers']);
557+
550558
/** Delete runtime */
551559
$response = $this->client->call(Client::METHOD_DELETE, '/runtimes/test-exec-coldstart', [], []);
552560
$this->assertEquals(200, $response['headers']['status-code']);

0 commit comments

Comments
 (0)