Skip to content

Commit 2edfe5b

Browse files
committed
fix: return HTTP 503 on fatal bootstrap error in index.php
Uncaught exceptions thrown during bootstrap (before Symfony starts) produced a PHP fatal error page with HTTP 200. Narrow the try-catch to only the env validation block so monitoring systems receive a 503 JSON response consistent with the monitor-bundle DOWN format, without interfering with response sending or kernel termination. Closes #1936
1 parent 5c3ca2a commit 2edfe5b

2 files changed

Lines changed: 37 additions & 9 deletions

File tree

public/index.php

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,29 @@
66

77
require dirname(__DIR__).'/vendor/autoload.php';
88

9-
// Validate required envs
10-
if (!isset($_ENV['APP_ENV'])) {
11-
throw new RuntimeException('APP_ENV environment variable is not defined.');
12-
}
13-
if (!isset($_ENV['APP_SECRET']) || trim($_ENV['APP_SECRET']) === '') {
14-
throw new \RuntimeException('APP_SECRET is missing or empty. Set it in your environment configuration.');
15-
}
16-
if ($_ENV['APP_ENV'] === 'prod' && strlen($_ENV['APP_SECRET']) < 32) {
17-
throw new \RuntimeException('APP_SECRET must be at least 32 characters long in production.');
9+
try {
10+
// Validate required envs
11+
if (!isset($_ENV['APP_ENV'])) {
12+
throw new RuntimeException('APP_ENV environment variable is not defined.');
13+
}
14+
if (!isset($_ENV['APP_SECRET']) || trim($_ENV['APP_SECRET']) === '') {
15+
throw new \RuntimeException('APP_SECRET is missing or empty. Set it in your environment configuration.');
16+
}
17+
if ($_ENV['APP_ENV'] === 'prod' && strlen($_ENV['APP_SECRET']) < 32) {
18+
throw new \RuntimeException('APP_SECRET must be at least 32 characters long in production.');
19+
}
20+
} catch (\Throwable $e) {
21+
http_response_code(503);
22+
header('Content-Type: application/json');
23+
$body = ['status' => 'DOWN'];
24+
if (trim($e->getMessage()) !== '') {
25+
$body['message'] = $e->getMessage();
26+
}
27+
error_log($e->getMessage());
28+
echo json_encode($body) ?: '{"status":"DOWN"}';
29+
exit;
1830
}
31+
1932
$debug = filter_var($_ENV['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN);
2033

2134
if ($debug) {

tests/functional/OpenConext/EngineBlockBundle/Controller/MonitorControllerTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,19 @@ public function internal_health_returns_json()
5050
$json = json_decode($response->getContent(), true, 512, JSON_THROW_ON_ERROR);
5151
$this->assertSame(['status' => 'UP'], $json);
5252
}
53+
54+
#[Test]
55+
#[Group('Monitor')]
56+
public function health_returns_json(): void
57+
{
58+
$client = self::createClient();
59+
$client->request('GET', 'https://engine.dev.openconext.local/health');
60+
61+
$response = $client->getResponse();
62+
$this->assertEquals(Response::HTTP_OK, $response->getStatusCode());
63+
$this->assertJson($response->getContent());
64+
65+
$json = json_decode($response->getContent(), true, 512, JSON_THROW_ON_ERROR);
66+
$this->assertSame(['status' => 'UP'], $json);
67+
}
5368
}

0 commit comments

Comments
 (0)