• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

api-platform / core / 6978607092

24 Nov 2023 08:43AM UTC coverage: 36.966% (-0.5%) from 37.474%
6978607092

push

github

web-flow
fix: errors bc with rfc_7807_compliant_errors false (#5974)

* fix: errors bc with rfc_7807_compliant_errors false

70 of 140 new or added lines in 19 files covered. (50.0%)

38 existing lines in 9 files now uncovered.

10179 of 27536 relevant lines covered (36.97%)

13.69 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.38
/src/Action/ExceptionAction.php
1
<?php
2

3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <dunglas@gmail.com>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11

12
declare(strict_types=1);
13

14
namespace ApiPlatform\Action;
15

16
use ApiPlatform\Metadata\ApiResource;
17
use ApiPlatform\Metadata\HttpOperation;
18
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
19
use ApiPlatform\State\Util\OperationRequestInitiatorTrait;
20
use ApiPlatform\Symfony\Util\RequestAttributesExtractor;
21
use ApiPlatform\Symfony\Validator\Exception\ConstraintViolationListAwareExceptionInterface;
22
use ApiPlatform\Util\ErrorFormatGuesser;
23
use Symfony\Component\ErrorHandler\Exception\FlattenException;
24
use Symfony\Component\HttpFoundation\Request;
25
use Symfony\Component\HttpFoundation\Response;
26
use Symfony\Component\Serializer\SerializerInterface;
27
use Symfony\Component\Validator\ConstraintViolationListInterface;
28

29
/**
30
 * Renders a normalized exception for a given see [FlattenException](https://github.com/symfony/symfony/blob/6.3/src/Symfony/Component/ErrorHandler/Exception/FlattenException.php).
31
 *
32
 * @author Baptiste Meyer <baptiste.meyer@gmail.com>
33
 * @author Kévin Dunglas <dunglas@gmail.com>
34
 *
35
 * @deprecated since API Platform 3 and Error resource is used {@see ApiPlatform\Symfony\EventListener\ErrorListener}
36
 */
37
final class ExceptionAction
38
{
39
    use OperationRequestInitiatorTrait;
40

41
    /**
42
     * @param array $errorFormats      A list of enabled error formats
43
     * @param array $exceptionToStatus A list of exceptions mapped to their HTTP status code
44
     */
45
    public function __construct(private readonly SerializerInterface $serializer, private readonly array $errorFormats, private readonly array $exceptionToStatus = [], ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null)
46
    {
47
        $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory;
48✔
48
    }
49

50
    /**
51
     * Converts an exception to a JSON response.
52
     */
53
    public function __invoke(FlattenException $exception, Request $request): Response
54
    {
55
        $operation = $this->initializeOperation($request);
48✔
56
        $exceptionClass = $exception->getClass();
48✔
57
        $statusCode = $exception->getStatusCode();
48✔
58

59
        $exceptionToStatus = array_merge(
48✔
60
            $this->exceptionToStatus,
48✔
61
            $operation ? $operation->getExceptionToStatus() ?? [] : $this->getOperationExceptionToStatus($request)
48✔
62
        );
48✔
63

64
        foreach ($exceptionToStatus as $class => $status) {
48✔
65
            if (is_a($exceptionClass, $class, true)) {
42✔
66
                $statusCode = $status;
39✔
67

68
                break;
39✔
69
            }
70
        }
71

72
        $headers = $exception->getHeaders();
48✔
73
        $format = ErrorFormatGuesser::guessErrorFormat($request, $this->errorFormats);
48✔
74
        $headers['Content-Type'] = sprintf('%s; charset=utf-8', $format['value'][0]);
48✔
75
        $headers['X-Content-Type-Options'] = 'nosniff';
48✔
76
        $headers['X-Frame-Options'] = 'deny';
48✔
77

78
        $context = ['statusCode' => $statusCode, 'rfc_7807_compliant_errors' => $operation?->getExtraProperties()['rfc_7807_compliant_errors'] ?? false];
48✔
79
        $error = $request->attributes->get('exception') ?? $exception;
48✔
80
        if ($error instanceof ConstraintViolationListAwareExceptionInterface) {
48✔
NEW
81
            $error = $error->getConstraintViolationList();
×
82
        } elseif (method_exists($error, 'getViolations') && $error->getViolations() instanceof ConstraintViolationListInterface) {
48✔
NEW
83
            $error = $error->getViolations();
×
84
        } else {
85
            $error = $exception;
48✔
86
        }
87

88
        $serializerFormat = $format['key'];
48✔
89
        if ('json' === $serializerFormat && 'application/problem+json' === $format['value'][0]) {
48✔
90
            $serializerFormat = 'jsonproblem';
3✔
91
        }
92

93
        return new Response($this->serializer->serialize($error, $serializerFormat, $context), $statusCode, $headers);
48✔
94
    }
95

96
    private function getOperationExceptionToStatus(Request $request): array
97
    {
98
        $attributes = RequestAttributesExtractor::extractAttributes($request);
6✔
99

100
        if ([] === $attributes) {
6✔
101
            return [];
6✔
102
        }
103

104
        $resourceMetadataCollection = $this->resourceMetadataCollectionFactory->create($attributes['resource_class']);
×
105
        /** @var HttpOperation $operation */
106
        $operation = $resourceMetadataCollection->getOperation($attributes['operation_name'] ?? null);
×
107
        $exceptionToStatus = [$operation->getExceptionToStatus() ?: []];
×
108

109
        foreach ($resourceMetadataCollection as $resourceMetadata) {
×
110
            /* @var ApiResource $resourceMetadata */
111
            $exceptionToStatus[] = $resourceMetadata->getExceptionToStatus() ?: [];
×
112
        }
113

114
        return array_merge(...$exceptionToStatus);
×
115
    }
116
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc