Skip to content

Commit 4f51b51

Browse files
authored
fix: use http exception headers (#5932)
fixes #5924
1 parent d9f7740 commit 4f51b51

File tree

4 files changed

+57
-0
lines changed

4 files changed

+57
-0
lines changed

features/main/exception_to_status.feature

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,10 @@ Feature: Using exception_to_status config
3838
And I send a "DELETE" request to "/error_with_overriden_status/1"
3939
Then the response status code should be 403
4040
And the JSON node "status" should be equal to 403
41+
42+
@!mongodb
43+
Scenario: Get HTTP Exception headers
44+
When I add "Accept" header equal to "application/ld+json"
45+
And I send a "GET" request to "/issue5924"
46+
Then the response status code should be 429
47+
Then the header "retry-after" should be equal to 32

src/State/Processor/RespondProcessor.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
namespace ApiPlatform\State\Processor;
1515

16+
use ApiPlatform\Metadata\Exception\HttpExceptionInterface;
1617
use ApiPlatform\Metadata\HttpOperation;
1718
use ApiPlatform\Metadata\IriConverterInterface;
1819
use ApiPlatform\Metadata\Operation;
@@ -24,6 +25,7 @@
2425
use ApiPlatform\Metadata\Util\CloneTrait;
2526
use ApiPlatform\State\ProcessorInterface;
2627
use Symfony\Component\HttpFoundation\Response;
28+
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface as SymfonyHttpExceptionInterface;
2729

2830
/**
2931
* Serializes data.
@@ -64,6 +66,11 @@ public function process(mixed $data, Operation $operation, array $uriVariables =
6466
'X-Frame-Options' => 'deny',
6567
];
6668

69+
$exception = $request->attributes->get('exception');
70+
if (($exception instanceof HttpExceptionInterface || $exception instanceof SymfonyHttpExceptionInterface) && $exceptionHeaders = $exception->getHeaders()) {
71+
$headers = array_merge($headers, $exceptionHeaders);
72+
}
73+
6774
$status = $operation->getStatus();
6875

6976
if ($sunset = $operation->getSunset()) {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
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\Tests\Fixtures\TestBundle\ApiResource\Issue5924;
15+
16+
use ApiPlatform\Metadata\Get;
17+
use ApiPlatform\Metadata\Operation;
18+
use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;
19+
20+
#[Get(uriTemplate: 'issue5924{._format}', read: true, provider: [TooManyRequests::class, 'provide'])]
21+
class TooManyRequests
22+
{
23+
public static function provide(Operation $operation, array $uriVariables = [], array $context = []): void
24+
{
25+
throw new TooManyRequestsHttpException(32);
26+
}
27+
}

tests/State/RespondProcessorTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use Prophecy\PhpUnit\ProphecyTrait;
2626
use Symfony\Component\HttpFoundation\Request;
2727
use Symfony\Component\HttpFoundation\Response;
28+
use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;
2829

2930
class RespondProcessorTest extends TestCase
3031
{
@@ -97,4 +98,19 @@ public function testRedirectToOperation(): void
9798
$this->assertSame(200, $response->getStatusCode());
9899
$this->assertNull($response->headers->get('Location'));
99100
}
101+
102+
public function testAddsExceptionHeaders(): void
103+
{
104+
$operation = new Get();
105+
106+
/** @var ProcessorInterface<Response> $respondProcessor */
107+
$respondProcessor = new RespondProcessor();
108+
$req = new Request();
109+
$req->attributes->set('exception', new TooManyRequestsHttpException(32));
110+
$response = $respondProcessor->process('content', new Get(), context: [
111+
'request' => $req,
112+
]);
113+
114+
$this->assertSame('32', $response->headers->get('retry-after'));
115+
}
100116
}

0 commit comments

Comments
 (0)