Skip to content

Commit

Permalink
fix: multiple error routes #6214 (#6263)
Browse files Browse the repository at this point in the history
  • Loading branch information
soyuka authored Mar 29, 2024
1 parent cf20566 commit 4adc075
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 3 deletions.
6 changes: 6 additions & 0 deletions src/Hydra/Serializer/DocumentationNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\CollectionOperationInterface;
use ApiPlatform\Metadata\ErrorResource;
use ApiPlatform\Metadata\HttpOperation;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
Expand All @@ -29,6 +30,7 @@
use ApiPlatform\Metadata\ResourceClassResolverInterface;
use ApiPlatform\Metadata\UrlGeneratorInterface;
use ApiPlatform\Serializer\CacheableSupportsMethodInterface;
use ApiPlatform\Symfony\Validator\Exception\ValidationException;
use Symfony\Component\PropertyInfo\Type;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
Expand Down Expand Up @@ -60,6 +62,10 @@ public function normalize(mixed $object, ?string $format = null, array $context
$resourceMetadataCollection = $this->resourceMetadataFactory->create($resourceClass);

$resourceMetadata = $resourceMetadataCollection[0];
if ($resourceMetadata instanceof ErrorResource && ValidationException::class === $resourceMetadata->getClass()) {
continue;
}

$shortName = $resourceMetadata->getShortName();
$prefixedShortName = $resourceMetadata->getTypes()[0] ?? "#$shortName";
$this->populateEntrypointProperties($resourceMetadata, $shortName, $prefixedShortName, $entrypointProperties, $resourceMetadataCollection);
Expand Down
2 changes: 1 addition & 1 deletion src/Metadata/Resource/Factory/OperationDefaultsTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ private function getOperationWithDefaults(ApiResource $resource, Operation $oper
throw new RuntimeException(sprintf('Operation should be an instance of "%s"', HttpOperation::class));
}

if ($operation->getRouteName()) {
if (!$operation->getName() && $operation->getRouteName()) {
/** @var HttpOperation $operation */
$operation = $operation->withName($operation->getRouteName());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public function create(string $resourceClass): ResourceMetadataCollection
$operation = $operation->withName($routeName);
}

$operations->add($routeName, $operation);
$operations->add($operation->getName(), $operation);
continue;
}

Expand Down
9 changes: 9 additions & 0 deletions src/State/ApiResource/Error.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
operations: [
new Operation(
name: '_api_errors_problem',
routeName: 'api_errors',
outputFormats: ['json' => ['application/problem+json']],
normalizationContext: [
'groups' => ['jsonproblem'],
Expand All @@ -42,6 +43,7 @@
),
new Operation(
name: '_api_errors_hydra',
routeName: 'api_errors',
outputFormats: ['jsonld' => ['application/problem+json']],
normalizationContext: [
'groups' => ['jsonld'],
Expand All @@ -52,13 +54,18 @@
),
new Operation(
name: '_api_errors_jsonapi',
routeName: 'api_errors',
outputFormats: ['jsonapi' => ['application/vnd.api+json']],
normalizationContext: [
'groups' => ['jsonapi'],
'skip_null_values' => true,
'rfc_7807_compliant_errors' => true,
],
),
new Operation(
name: '_api_errors',
routeName: 'api_errors'
),
],
provider: 'api_platform.state.error_provider',
graphQlOperations: []
Expand Down Expand Up @@ -120,12 +127,14 @@ public static function createFromException(\Exception|\Throwable $exception, int
}

#[Ignore]
#[ApiProperty(readable: false)]
public function getHeaders(): array
{
return $this->headers;
}

#[Ignore]
#[ApiProperty(readable: false)]
public function getStatusCode(): int
{
return $this->status;
Expand Down
11 changes: 11 additions & 0 deletions src/Symfony/Bundle/Resources/config/routing/api.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,15 @@
<requirement key="index">index</requirement>
</route>

<route id="api_errors" path="/errors/{status}">
<default key="_controller">api_platform.action.not_exposed</default>
<default key="status">500</default>

<requirement key="status">\d+</requirement>
</route>

<route id="api_validation_errors" path="/validation_errors/{id}">
<default key="_controller">api_platform.action.not_exposed</default>
</route>

</routes>
4 changes: 3 additions & 1 deletion src/Symfony/Routing/IriConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,9 @@ private function generateSymfonyRoute(object|string $resource, int $referenceTyp
}

try {
return $this->router->generate($operation->getName(), $identifiers, $operation->getUrlGenerationStrategy() ?? $referenceType);
$routeName = $operation instanceof HttpOperation ? ($operation->getRouteName() ?? $operation->getName()) : $operation->getName();

return $this->router->generate($routeName, $identifiers, $operation->getUrlGenerationStrategy() ?? $referenceType);
} catch (RoutingExceptionInterface $e) {
throw new InvalidArgumentException(sprintf('Unable to generate an IRI for the item of type "%s"', $operation->getClass()), $e->getCode(), $e);
}
Expand Down
7 changes: 7 additions & 0 deletions src/Symfony/Validator/Exception/ValidationException.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@
operations: [
new ErrorOperation(
name: '_api_validation_errors_problem',
routeName: 'api_validation_errors',
outputFormats: ['json' => ['application/problem+json']],
normalizationContext: ['groups' => ['json'],
'skip_null_values' => true,
'rfc_7807_compliant_errors' => true,
]),
new ErrorOperation(
name: '_api_validation_errors_hydra',
routeName: 'api_validation_errors',
outputFormats: ['jsonld' => ['application/problem+json']],
links: [new Link(rel: ContextBuilderInterface::JSONLD_NS.'error', href: 'http://www.w3.org/ns/hydra/error')],
normalizationContext: [
Expand All @@ -57,9 +59,14 @@
),
new ErrorOperation(
name: '_api_validation_errors_jsonapi',
routeName: 'api_validation_errors',
outputFormats: ['jsonapi' => ['application/vnd.api+json']],
normalizationContext: ['groups' => ['jsonapi'], 'skip_null_values' => true, 'rfc_7807_compliant_errors' => true]
),
new ErrorOperation(
name: '_api_validation_errors',
routeName: 'api_validation_errors'
),
],
graphQlOperations: []
)]
Expand Down

0 comments on commit 4adc075

Please sign in to comment.