Skip to content

Commit 55cebe8

Browse files
authored
Merge pull request #63 from oparshyna/feat/add_custom_error_status_code
feat: add custom response error code
2 parents d7c56c9 + 22eda82 commit 55cebe8

File tree

15 files changed

+253
-62
lines changed

15 files changed

+253
-62
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77

88
jobs:
99
run:
10-
runs-on: ubuntu-18.04
10+
runs-on: ubuntu-latest
1111
strategy:
1212
fail-fast: false
1313
matrix:

README.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,18 @@ symfony_health_check:
7171
ping_checks:
7272
- id: symfony_health_check.status_up_check
7373
```
74+
Change response code:
75+
- default response code is 200.
76+
- determine your custom response code in case of some check fails (Response code must be a valid HTTP status code)
77+
```yaml
78+
symfony_health_check:
79+
health_checks:
80+
- id: symfony_health_check.doctrine_check
81+
ping_checks:
82+
- id: symfony_health_check.status_up_check
83+
ping_error_response_code: 500
84+
health_error_response_code: 404
85+
```
7486
7587
Create Symfony Health Check Bundle Routing Config:
7688
----------------------------------
@@ -141,12 +153,12 @@ You can change the default behavior with a light configuration, remember to retu
141153
health:
142154
path: /your/custom/url
143155
methods: GET
144-
controller: SymfonyHealthCheckBundle\Controller\HealthController::healthCheckAction
156+
controller: SymfonyHealthCheckBundle\Controller\HealthController::check
145157
146158
ping:
147159
path: /your/custom/url
148160
methods: GET
149-
controller: SymfonyHealthCheckBundle\Controller\PingController::pingAction
161+
controller: SymfonyHealthCheckBundle\Controller\PingController::check
150162
151163
```
152164

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"require-dev": {
3636
"ext-json": "*",
3737
"phpstan/phpstan": "1.9.*",
38-
"squizlabs/php_codesniffer": "3.5.*",
38+
"squizlabs/php_codesniffer": "3.7.*",
3939
"symfony/phpunit-bridge": "^3.4 || ^4.1.12 || ^5.0 || ^6.0",
4040
"phpunit/phpunit": "^8.5 || ^9.0",
4141
"symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0",

phpstan-baseline.neon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
parameters:
22
ignoreErrors:
33
-
4-
message: '#Call to an undefined method Symfony\\Component\\Config\\Definition\\Builder\\NodeDefinition::children\(\).#'
4+
message: '#Call to an undefined method Symfony\\Component\\Config\\Definition\\Builder\\NodeParentInterface::variableNode\(\).#'
55
count: 1
66
path: ./src/DependencyInjection
77
-

src/Check/DoctrineCheck.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ public function check(): Response
2525
return new Response(self::CHECK_RESULT_NAME, false, 'Entity Manager Not Found.');
2626
}
2727

28+
/**
29+
* @var object|null $entityManager
30+
*/
2831
$entityManager = $this->container->get('doctrine.orm.entity_manager');
2932

3033
if ($entityManager === null) {

src/Controller/BaseController.php

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SymfonyHealthCheckBundle\Controller;
6+
7+
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
8+
use Symfony\Component\HttpFoundation\JsonResponse;
9+
use Symfony\Component\HttpFoundation\Response;
10+
use SymfonyHealthCheckBundle\Check\CheckInterface;
11+
12+
abstract class BaseController extends AbstractController
13+
{
14+
/**
15+
* @var array<CheckInterface>
16+
*/
17+
private array $checks = [];
18+
private ?int $customResponseCode = null;
19+
20+
abstract public function check(): JsonResponse;
21+
22+
public function addHealthCheck(CheckInterface $check): void
23+
{
24+
$this->checks[] = $check;
25+
}
26+
27+
public function setCustomResponseCode(?int $code): void
28+
{
29+
$this->customResponseCode = $code;
30+
}
31+
32+
protected function checkAction(): JsonResponse
33+
{
34+
$checkResult = $this->performCheck();
35+
$responseCode = $this->determineResponseCode($checkResult);
36+
37+
return new JsonResponse($checkResult, $responseCode);
38+
}
39+
40+
protected function performCheck(): array
41+
{
42+
return array_map(
43+
fn($healthCheck) => $healthCheck->check()->toArray(),
44+
$this->checks
45+
);
46+
}
47+
48+
protected function determineResponseCode(array $results): int
49+
{
50+
$code = $this->customResponseCode;
51+
$responseCode = Response::HTTP_OK;
52+
53+
if (null !== $code) {
54+
foreach ($results as $result) {
55+
if (!$result['result']) {
56+
$responseCode = $code;
57+
break;
58+
}
59+
}
60+
}
61+
62+
return $responseCode;
63+
}
64+
}

src/Controller/HealthController.php

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,20 @@
44

55
namespace SymfonyHealthCheckBundle\Controller;
66

7-
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
87
use Symfony\Component\HttpFoundation\JsonResponse;
9-
use Symfony\Component\HttpFoundation\Response;
108
use Symfony\Component\Routing\Annotation\Route;
11-
use SymfonyHealthCheckBundle\Check\CheckInterface;
129

13-
final class HealthController extends AbstractController
10+
final class HealthController extends BaseController
1411
{
15-
/**
16-
* @var array<CheckInterface>
17-
*/
18-
private array $healthChecks = [];
19-
20-
public function addHealthCheck(CheckInterface $healthCheck): void
21-
{
22-
$this->healthChecks[] = $healthCheck;
23-
}
24-
2512
/**
2613
* @Route(
2714
* path="/health",
2815
* name="health",
2916
* methods={"GET"}
3017
* )
3118
*/
32-
public function healthCheckAction(): JsonResponse
19+
public function check(): JsonResponse
3320
{
34-
$resultHealthCheck = [];
35-
foreach ($this->healthChecks as $healthCheck) {
36-
$resultHealthCheck[] = $healthCheck->check()->toArray();
37-
}
38-
39-
return new JsonResponse($resultHealthCheck, Response::HTTP_OK);
21+
return $this->checkAction();
4022
}
4123
}

src/Controller/PingController.php

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,20 @@
44

55
namespace SymfonyHealthCheckBundle\Controller;
66

7-
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
87
use Symfony\Component\HttpFoundation\JsonResponse;
9-
use Symfony\Component\HttpFoundation\Response;
108
use Symfony\Component\Routing\Annotation\Route;
11-
use SymfonyHealthCheckBundle\Check\CheckInterface;
129

13-
final class PingController extends AbstractController
10+
final class PingController extends BaseController
1411
{
15-
/**
16-
* @var array<CheckInterface>
17-
*/
18-
private array $checks = [];
19-
20-
public function addHealthCheck(CheckInterface $check): void
21-
{
22-
$this->checks[] = $check;
23-
}
24-
2512
/**
2613
* @Route(
2714
* path="/ping",
2815
* name="ping",
2916
* methods={"GET"}
3017
* )
3118
*/
32-
public function pingAction(): JsonResponse
19+
public function check(): JsonResponse
3320
{
34-
$pingCheck = [];
35-
foreach ($this->checks as $healthCheck) {
36-
$pingCheck[] = $healthCheck->check()->toArray();
37-
}
38-
39-
return new JsonResponse($pingCheck, Response::HTTP_OK);
21+
return $this->checkAction();
4022
}
4123
}

src/DependencyInjection/Configuration.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
88
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
99
use Symfony\Component\Config\Definition\ConfigurationInterface;
10+
use Symfony\Component\HttpFoundation\Response;
1011

1112
class Configuration implements ConfigurationInterface
1213
{
@@ -21,6 +22,24 @@ public function getConfigTreeBuilder(): TreeBuilder
2122

2223
$root
2324
->children()
25+
->variableNode('ping_error_response_code')
26+
->defaultValue(null)
27+
->validate()
28+
->ifTrue(function ($value) {
29+
return $value !== null && !array_key_exists($value, Response::$statusTexts);
30+
})
31+
->thenInvalid('The ping_error_response_code must be valid HTTP status code or null.')
32+
->end()
33+
->end()
34+
->variableNode('health_error_response_code')
35+
->defaultValue(null)
36+
->validate()
37+
->ifTrue(function ($value) {
38+
return $value !== null && !array_key_exists($value, Response::$statusTexts);
39+
})
40+
->thenInvalid('The health_error_response_code must be valid HTTP status code or null.')
41+
->end()
42+
->end()
2443
->arrayNode('health_checks')
2544
->prototype('array')
2645
->children()

src/DependencyInjection/SymfonyHealthCheckExtension.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,14 @@ private function loadHealthChecks(
3737
foreach ($config['health_checks'] as $healthCheckConfig) {
3838
$healthCheckDefinition = new Reference($healthCheckConfig['id']);
3939
$healthCheckCollection->addMethodCall('addHealthCheck', [$healthCheckDefinition]);
40+
$healthCheckCollection->addMethodCall('setCustomResponseCode', [$config['health_error_response_code']]);
4041
}
4142

4243
$pingCollection = $container->findDefinition(PingController::class);
4344
foreach ($config['ping_checks'] as $healthCheckConfig) {
4445
$healthCheckDefinition = new Reference($healthCheckConfig['id']);
4546
$pingCollection->addMethodCall('addHealthCheck', [$healthCheckDefinition]);
47+
$pingCollection->addMethodCall('setCustomResponseCode', [$config['ping_error_response_code']]);
4648
}
4749
}
4850
}

0 commit comments

Comments
 (0)