-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
IBX-8173: Implemented routing language expression extension handling …
…`Content-Type` header
- Loading branch information
Showing
10 changed files
with
235 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
src/bundle/Routing/ExpressionLanguage/ContentTypeHeaderMatcherExpressionFunction.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<?php | ||
|
||
/** | ||
* @copyright Copyright (C) Ibexa AS. All rights reserved. | ||
* @license For full copyright and license information view LICENSE file distributed with this source code. | ||
*/ | ||
declare(strict_types=1); | ||
|
||
namespace Ibexa\Bundle\Rest\Routing\ExpressionLanguage; | ||
|
||
use Ibexa\Contracts\Rest\Input\MediaTypeParserInterface; | ||
use Symfony\Component\HttpFoundation\Request; | ||
|
||
final readonly class ContentTypeHeaderMatcherExpressionFunction | ||
{ | ||
public function __construct( | ||
private MediaTypeParserInterface $mediaTypeParser | ||
) { | ||
} | ||
|
||
public function __invoke(Request $request): ?string | ||
{ | ||
$contentTypeHeaderValue = $request->headers->get('Content-Type'); | ||
if ($contentTypeHeaderValue === null) { | ||
return null; | ||
} | ||
|
||
return $this->mediaTypeParser->parseContentTypeHeader($contentTypeHeaderValue); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?php | ||
|
||
/** | ||
* @copyright Copyright (C) Ibexa AS. All rights reserved. | ||
* @license For full copyright and license information view LICENSE file distributed with this source code. | ||
*/ | ||
declare(strict_types=1); | ||
|
||
namespace Ibexa\Contracts\Rest\Input; | ||
|
||
final class MediaTypeParser implements MediaTypeParserInterface | ||
{ | ||
private const string MEDIA_TYPE_PATTERN = '/application\/vnd\.ibexa\.api\.([^.]+)\+/'; | ||
|
||
public function parseContentTypeHeader(string $header): ?string | ||
{ | ||
if (preg_match(self::MEDIA_TYPE_PATTERN, $header, $matches)) { | ||
return $matches[1]; | ||
} | ||
|
||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?php | ||
|
||
/** | ||
* @copyright Copyright (C) Ibexa AS. All rights reserved. | ||
* @license For full copyright and license information view LICENSE file distributed with this source code. | ||
*/ | ||
declare(strict_types=1); | ||
|
||
namespace Ibexa\Contracts\Rest\Input; | ||
|
||
interface MediaTypeParserInterface | ||
{ | ||
public function parseContentTypeHeader(string $header): ?string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
tests/bundle/Routing/ExpressionLanguage/ContentTypeHeaderMatcherExpressionFunctionTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<?php | ||
|
||
/** | ||
* @copyright Copyright (C) Ibexa AS. All rights reserved. | ||
* @license For full copyright and license information view LICENSE file distributed with this source code. | ||
*/ | ||
declare(strict_types=1); | ||
|
||
namespace Ibexa\Tests\Bundle\Rest\Routing\ExpressionLanguage; | ||
|
||
use Ibexa\Bundle\Rest\Routing\ExpressionLanguage\ContentTypeHeaderMatcherExpressionFunction; | ||
use Ibexa\Contracts\Rest\Input\MediaTypeParser; | ||
use PHPUnit\Framework\TestCase; | ||
use Symfony\Component\HttpFoundation\Request; | ||
|
||
final class ContentTypeHeaderMatcherExpressionFunctionTest extends TestCase | ||
{ | ||
private readonly ContentTypeHeaderMatcherExpressionFunction $contentTypeHeaderMatcher; | ||
|
||
protected function setUp(): void | ||
{ | ||
$contentTypeHeaderMatcher = new ContentTypeHeaderMatcherExpressionFunction( | ||
new MediaTypeParser(), | ||
); | ||
$this->contentTypeHeaderMatcher = $contentTypeHeaderMatcher; | ||
} | ||
|
||
public function testGetMediaType(): void | ||
{ | ||
$request = new Request(); | ||
$request->headers->add([ | ||
'Content-Type' => 'application/vnd.ibexa.api.CopyContentTypeInput+json', | ||
]); | ||
|
||
$closure = $this->contentTypeHeaderMatcher; | ||
|
||
self::assertSame('CopyContentTypeInput', $closure($request)); | ||
} | ||
|
||
public function testRequestContentTypeDoesNotMatchRoute(): void | ||
{ | ||
$request = new Request(); | ||
$request->headers->add([ | ||
'Content-Type' => 'application.CreateContentTypeInput+xml', | ||
]); | ||
|
||
$closure = $this->contentTypeHeaderMatcher; | ||
|
||
self::assertNull($closure($request)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<?php | ||
|
||
/** | ||
* @copyright Copyright (C) Ibexa AS. All rights reserved. | ||
* @license For full copyright and license information view LICENSE file distributed with this source code. | ||
*/ | ||
declare(strict_types=1); | ||
|
||
namespace Ibexa\Tests\Rest\Input; | ||
|
||
use Ibexa\Contracts\Rest\Input\MediaTypeParser; | ||
use Ibexa\Contracts\Rest\Input\MediaTypeParserInterface; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
final class MediaTypeParserTest extends TestCase | ||
{ | ||
private readonly MediaTypeParserInterface $mediaTypeParser; | ||
|
||
protected function setUp(): void | ||
{ | ||
$this->mediaTypeParser = new MediaTypeParser(); | ||
} | ||
|
||
public function testParsingSuccesses(): void | ||
{ | ||
$header = 'application/vnd.ibexa.api.CopyContentTypeInput+json'; | ||
|
||
self::assertSame('CopyContentTypeInput', $this->mediaTypeParser->parseContentTypeHeader($header)); | ||
} | ||
|
||
/** | ||
* @dataProvider providerForParsingFails | ||
*/ | ||
public function testParsingFails(string $header): void | ||
{ | ||
self::assertNull($this->mediaTypeParser->parseContentTypeHeader($header)); | ||
} | ||
|
||
/** | ||
* @return iterable<array<int, string>> | ||
*/ | ||
public function providerForParsingFails(): iterable | ||
{ | ||
yield 'a' => ['application.CopyContentTypeInput+json']; | ||
yield 'b' => ['application.CopyContentTypeInput']; | ||
yield 'c' => ['CopyContentTypeInput+json']; | ||
yield 'd' => ['CopyContentTypeInput']; | ||
} | ||
} |