Skip to content

Commit 48ac4f0

Browse files
committed
reworked the solution to have a whitelist of formats instead
1 parent 7eaca52 commit 48ac4f0

File tree

4 files changed

+92
-94
lines changed

4 files changed

+92
-94
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
declare(strict_types=1);
8+
9+
namespace Ibexa\Bundle\Rest\EventListener;
10+
11+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
12+
use Symfony\Component\HttpFoundation\Response;
13+
use Symfony\Component\HttpKernel\Event\RequestEvent;
14+
use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
15+
use Symfony\Component\HttpKernel\KernelEvents;
16+
17+
final class SupportedMediaTypesSubscriber implements EventSubscriberInterface
18+
{
19+
private const SUPPORTED_MEDIA_TYPES_PATTERN = '(^application/vnd\.ibexa\.api(\.[A-Za-z]+)+\+%s$)';
20+
21+
public static function getSubscribedEvents(): array
22+
{
23+
return [
24+
KernelEvents::REQUEST => [
25+
['allowOnlySupportedMediaTypes', 0],
26+
],
27+
];
28+
}
29+
30+
public function allowOnlySupportedMediaTypes(RequestEvent $event): void
31+
{
32+
$request = $event->getRequest();
33+
if (!$request->attributes->has('supported_media_types')) {
34+
return;
35+
}
36+
37+
$supportedMediaTypes = $request->attributes->get('supported_media_types');
38+
$regexps = array_map(
39+
static fn (string $mediaType): string => sprintf(
40+
self::SUPPORTED_MEDIA_TYPES_PATTERN,
41+
strtolower($mediaType)
42+
),
43+
$supportedMediaTypes
44+
);
45+
46+
$contentTypeHeader = $request->headers->get('Content-Type') ?? '';
47+
$acceptHeader = $request->headers->get('Accept') ?? '';
48+
49+
foreach ($regexps as $regexp) {
50+
if (
51+
preg_match($regexp, $contentTypeHeader) === 1
52+
|| preg_match($regexp, $acceptHeader) === 1
53+
) {
54+
break;
55+
}
56+
57+
throw new UnsupportedMediaTypeHttpException(
58+
sprintf(
59+
'Unsupported media type was used. Available ones are: %s',
60+
implode(', ', $supportedMediaTypes)
61+
),
62+
null,
63+
Response::HTTP_UNSUPPORTED_MEDIA_TYPE
64+
);
65+
}
66+
}
67+
}

src/bundle/EventListener/XmlUnsupportedMediaTypeSubscriber.php

Lines changed: 0 additions & 65 deletions
This file was deleted.

src/bundle/Resources/config/services.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,7 @@ services:
235235
- { name: kernel.event_subscriber }
236236
- { name: monolog.logger, channel: request }
237237

238-
Ibexa\Bundle\Rest\EventListener\XmlUnsupportedMediaTypeSubscriber:
239-
arguments:
240-
$xmlRegexps: '%ibexa.rest.output.visitor.xml.regexps%'
238+
Ibexa\Bundle\Rest\EventListener\SupportedMediaTypesSubscriber:
241239
tags:
242240
- { name: kernel.event_subscriber }
243241

tests/bundle/EventListener/XmlUnsupportedMediaTypeSubscriberTest.php renamed to tests/bundle/EventListener/SupportedMediaTypesSubscriberTest.php

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@
88

99
namespace Ibexa\Tests\Bundle\Rest\EventListener;
1010

11-
use Ibexa\Bundle\Rest\EventListener\XmlUnsupportedMediaTypeSubscriber;
11+
use Ibexa\Bundle\Rest\EventListener\SupportedMediaTypesSubscriber;
1212
use PHPUnit\Framework\TestCase;
1313
use Symfony\Component\HttpFoundation\HeaderBag;
1414
use Symfony\Component\HttpFoundation\Request;
1515
use Symfony\Component\HttpKernel\Event\RequestEvent;
1616
use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
1717
use Symfony\Component\HttpKernel\HttpKernelInterface;
1818

19-
final class XmlUnsupportedMediaTypeSubscriberTest extends TestCase
19+
final class SupportedMediaTypesSubscriberTest extends TestCase
2020
{
21-
private const XML_REGEXP = '(^application/vnd\.ibexa\.api(\.[A-Za-z]+)+\+xml$)';
21+
private const XML_REGEXP = '^application/vnd\.ibexa\.api(\.[A-Za-z]+)+\+xml$';
2222

2323
/** @var \Symfony\Component\HttpKernel\HttpKernelInterface&\PHPUnit\Framework\MockObject\MockObject */
2424
private HttpKernelInterface $kernel;
@@ -30,76 +30,74 @@ protected function setUp(): void
3030
$this->kernel = $this->createMock(HttpKernelInterface::class);
3131
}
3232

33-
public function testDoesNothingWhenXmlDisabledIsNotTrue(): void
33+
public function testDoesNothingWhenSupportedMediaTypesParameterIsNotSet(): void
3434
{
3535
$request = new Request();
36-
$request->attributes->set('xml_disabled', false);
37-
3836
$event = new RequestEvent($this->kernel, $request, HttpKernelInterface::MAIN_REQUEST);
3937

40-
$subscriber = new XmlUnsupportedMediaTypeSubscriber([self::XML_REGEXP]);
41-
$subscriber->blockXmlUnsupportedMediaType($event);
38+
$subscriber = new SupportedMediaTypesSubscriber();
39+
$subscriber->allowOnlySupportedMediaTypes($event);
4240

4341
self::expectNotToPerformAssertions();
4442
}
4543

46-
public function testDoesNothingWhenNoRegexps(): void
44+
public function testDoesNothingWhenSupportedMediaTypesParameterIsEmpty(): void
4745
{
4846
$request = new Request();
49-
$request->attributes->set('xml_disabled', true);
47+
$request->attributes->set('supported_media_types', []);
5048

51-
$subscriber = new XmlUnsupportedMediaTypeSubscriber([]);
49+
$subscriber = new SupportedMediaTypesSubscriber();
5250
$event = new RequestEvent($this->kernel, $request, HttpKernelInterface::MAIN_REQUEST);
5351

54-
$subscriber->blockXmlUnsupportedMediaType($event);
52+
$subscriber->allowOnlySupportedMediaTypes($event);
5553

5654
self::expectNotToPerformAssertions();
5755
}
5856

59-
public function testDoesNothingWhenNoMatch(): void
57+
public function testDoesNothingWhenMediaTypeIsSupported(): void
6058
{
6159
$request = new Request();
62-
$request->attributes->set('xml_disabled', true);
60+
$request->attributes->set('supported_media_types', ['json', 'xml']);
6361
$request->headers = new HeaderBag([
64-
'Content-Type' => 'application/json',
65-
'Accept' => 'application/json',
62+
'Content-Type' => 'application/vnd.ibexa.api.ContentCreat+json',
63+
'Accept' => 'application/vnd.ibexa.api.ContentCreat+json',
6664
]);
6765

68-
$subscriber = new XmlUnsupportedMediaTypeSubscriber([self::XML_REGEXP]);
66+
$subscriber = new SupportedMediaTypesSubscriber();
6967
$event = new RequestEvent($this->kernel, $request, HttpKernelInterface::MAIN_REQUEST);
7068

71-
$subscriber->blockXmlUnsupportedMediaType($event);
69+
$subscriber->allowOnlySupportedMediaTypes($event);
7270

7371
self::expectNotToPerformAssertions();
7472
}
7573

76-
public function testThrowsExceptionWhenContentTypeHeaderMatches(): void
74+
public function testThrowsExceptionWhenContentTypeHeaderTypeIsNotSupported(): void
7775
{
7876
$request = new Request();
79-
$request->attributes->set('xml_disabled', true);
77+
$request->attributes->set('supported_media_types', ['json']);
8078
$request->headers = new HeaderBag([
8179
'Content-Type' => 'application/vnd.ibexa.api.ContentCreate+xml',
8280
]);
8381

84-
$subscriber = new XmlUnsupportedMediaTypeSubscriber([self::XML_REGEXP]);
82+
$subscriber = new SupportedMediaTypesSubscriber();
8583
$event = new RequestEvent($this->kernel, $request, HttpKernelInterface::MAIN_REQUEST);
8684

8785
$this->expectException(UnsupportedMediaTypeHttpException::class);
88-
$subscriber->blockXmlUnsupportedMediaType($event);
86+
$subscriber->allowOnlySupportedMediaTypes($event);
8987
}
9088

91-
public function testThrowsExceptionWhenAcceptHeaderMatches(): void
89+
public function testThrowsExceptionWhenAcceptHeaderTypeIsNotSupported(): void
9290
{
9391
$request = new Request();
94-
$request->attributes->set('xml_disabled', true);
92+
$request->attributes->set('supported_media_types', ['json']);
9593
$request->headers = new HeaderBag([
9694
'Accept' => 'application/vnd.ibexa.api.ContentCreate+xml',
9795
]);
9896

99-
$subscriber = new XmlUnsupportedMediaTypeSubscriber([self::XML_REGEXP]);
97+
$subscriber = new SupportedMediaTypesSubscriber();
10098
$event = new RequestEvent($this->kernel, $request, HttpKernelInterface::MAIN_REQUEST);
10199

102100
$this->expectException(UnsupportedMediaTypeHttpException::class);
103-
$subscriber->blockXmlUnsupportedMediaType($event);
101+
$subscriber->allowOnlySupportedMediaTypes($event);
104102
}
105103
}

0 commit comments

Comments
 (0)