diff --git a/src/Symfony/Bundle/SwaggerUi/SwaggerUiProvider.php b/src/Symfony/Bundle/SwaggerUi/SwaggerUiProvider.php index 1304b852fdd..f47dda92337 100644 --- a/src/Symfony/Bundle/SwaggerUi/SwaggerUiProvider.php +++ b/src/Symfony/Bundle/SwaggerUi/SwaggerUiProvider.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Symfony\Bundle\SwaggerUi; use ApiPlatform\Documentation\Documentation; +use ApiPlatform\Documentation\Entrypoint; use ApiPlatform\Metadata\Error; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\HttpOperation; @@ -44,6 +45,7 @@ public function provide(Operation $operation, array $uriVariables = [], array $c !($operation instanceof HttpOperation) || !($request = $context['request'] ?? null) || 'html' !== $request->getRequestFormat() + || true === ($operation->getExtraProperties()['_api_disable_swagger_provider'] ?? false) ) { return $this->decorated->provide($operation, $uriVariables, $context); } @@ -55,11 +57,12 @@ public function provide(Operation $operation, array $uriVariables = [], array $c // We need to call our operation provider just in case it fails // when it fails we'll get an Error and we'll fix the status accordingly // @see features/main/content_negotiation.feature:119 - // DocumentationAction has no content negotation as well we want HTML so render swagger ui - if (!$operation instanceof Error && Documentation::class !== $operation->getClass()) { + // When requesting DocumentationAction or EntrypointAction with Accept: text/html we render SwaggerUi + if (!$operation instanceof Error && !\in_array($operation->getClass(), [Documentation::class, Entrypoint::class], true)) { $this->decorated->provide($operation, $uriVariables, $context); } + // This should render only when an error occured $swaggerUiOperation = new Get( class: OpenApi::class, processor: 'api_platform.swagger_ui.processor', @@ -71,7 +74,6 @@ class: OpenApi::class, // save our operation $request->attributes->set('_api_operation', $swaggerUiOperation); - $data = $this->openApiFactory->__invoke(['base_url' => $request->getBaseUrl() ?: '/']); $request->attributes->set('data', $data); diff --git a/tests/Fixtures/TestBundle/ApiResource/Issue6384/AcceptHtml.php b/tests/Fixtures/TestBundle/ApiResource/Issue6384/AcceptHtml.php new file mode 100644 index 00000000000..abe3560ed51 --- /dev/null +++ b/tests/Fixtures/TestBundle/ApiResource/Issue6384/AcceptHtml.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue6384; + +use ApiPlatform\Metadata\Get; +use Symfony\Component\HttpFoundation\Response; + +#[Get( + uriTemplate: 'accept_html', + provider: [self::class, 'provide'], + outputFormats: ['html' => ['text/html']], + formats: ['html' => ['text/html']], + extraProperties: ['_api_disable_swagger_provider' => true] +)] +class AcceptHtml +{ + public static function provide(): Response + { + return new Response('

hello

'); + } +} diff --git a/tests/Functional/FormatTest.php b/tests/Functional/FormatTest.php new file mode 100644 index 00000000000..9dbd4c15e81 --- /dev/null +++ b/tests/Functional/FormatTest.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Functional; + +use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; + +final class FormatTest extends ApiTestCase +{ + public function testShouldReturnHtml(): void + { + $r = self::createClient()->request('GET', '/accept_html', ['headers' => ['Accept' => 'text/html']]); + $this->assertResponseIsSuccessful(); + $this->assertEquals($r->getContent(), '

hello

'); + } +}