[Schema] fix: allow URIs without double slash in Resource and ResourceTemplate (RFC 3986) (#297)
* fix: allow URIs without double slash in Resource and ResourceTemplate (RFC 3986) The URI regex required "://" after the scheme, rejecting valid URIs like urn:isbn:123, mailto:user@example.com, config:key, and data: URIs. RFC 3986 only requires ":" after the scheme; the "//" is part of the authority component which is optional. Changed both Resource.URI_PATTERN and ResourceTemplate.URI_TEMPLATE_PATTERN to require ":" instead of "://". Adds data-provider tests for URIs without double slash in both classes. Fixes #293 * Reword unit tests --------- Co-authored-by: Christopher Hertel <mail@christopher-hertel.de>
This commit is contained in:
parent
a929548f33
commit
797472777f
4 changed files with 46 additions and 6 deletions
|
|
@ -40,10 +40,10 @@ class Resource implements \JsonSerializable
|
|||
private const RESOURCE_NAME_PATTERN = '/^[a-zA-Z0-9_-]+$/';
|
||||
|
||||
/**
|
||||
* URI pattern regex - requires a valid scheme, followed by colon and optional path.
|
||||
* Example patterns: config://, file://path, db://table, etc.
|
||||
* URI pattern regex - requires a valid scheme followed by colon and optional path (RFC 3986).
|
||||
* Example patterns: file://path, db://table, urn:isbn:123, config:key, etc.
|
||||
*/
|
||||
private const URI_PATTERN = '/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\/[^\s]*$/';
|
||||
private const URI_PATTERN = '/^[a-zA-Z][a-zA-Z0-9+.-]*:[^\s]*$/';
|
||||
|
||||
/**
|
||||
* @param string $uri the URI of this resource
|
||||
|
|
|
|||
|
|
@ -37,10 +37,10 @@ class ResourceTemplate implements \JsonSerializable
|
|||
private const RESOURCE_NAME_PATTERN = '/^[a-zA-Z0-9_-]+$/';
|
||||
|
||||
/**
|
||||
* URI Template pattern regex - requires a valid scheme, followed by colon and path with at least one placeholder.
|
||||
* Example patterns: config://{key}, file://{path}/contents.txt, db://{table}/{id}, etc.
|
||||
* URI Template pattern regex - requires a valid scheme followed by colon and path with at least one placeholder (RFC 3986).
|
||||
* Example patterns: file://{path}/contents.txt, db://{table}/{id}, config:{key}, etc.
|
||||
*/
|
||||
private const URI_TEMPLATE_PATTERN = '/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\/.*{[^{}]+}.*/';
|
||||
private const URI_TEMPLATE_PATTERN = '/^[a-zA-Z][a-zA-Z0-9+.-]*:.*{[^{}]+}.*/';
|
||||
|
||||
/**
|
||||
* @param string $uriTemplate a URI template (according to RFC 6570) that can be used to construct resource URIs
|
||||
|
|
|
|||
|
|
@ -46,6 +46,25 @@ class ResourceTemplateTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
#[DataProvider('provideValidTemplates')]
|
||||
public function testConstructorAcceptsTemplates(string $uriTemplate): void
|
||||
{
|
||||
$resource = new ResourceTemplate(
|
||||
uriTemplate: $uriTemplate,
|
||||
name: 'test-template',
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(ResourceTemplate::class, $resource);
|
||||
$this->assertSame($uriTemplate, $resource->uriTemplate);
|
||||
}
|
||||
|
||||
public static function provideValidTemplates(): iterable
|
||||
{
|
||||
yield 'custom scheme without slashes' => ['config:{key}'];
|
||||
yield 'custom scheme with slashes' => ['config://{key}'];
|
||||
yield 'urn-style template' => ['urn:resource:{id}'];
|
||||
}
|
||||
|
||||
public function testFromArrayValid(): void
|
||||
{
|
||||
$resource = ResourceTemplate::fromArray([
|
||||
|
|
|
|||
|
|
@ -46,6 +46,27 @@ class ResourceTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
#[DataProvider('provideValidUris')]
|
||||
public function testConstructorAcceptsUris(string $uri): void
|
||||
{
|
||||
$resource = new Resource(
|
||||
uri: $uri,
|
||||
name: 'test-resource',
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(Resource::class, $resource);
|
||||
$this->assertSame($uri, $resource->uri);
|
||||
}
|
||||
|
||||
public static function provideValidUris(): iterable
|
||||
{
|
||||
yield 'urn' => ['urn:isbn:0451450523'];
|
||||
yield 'mailto' => ['mailto:user@example.com'];
|
||||
yield 'data' => ['data:text/plain;base64,SGVsbG8='];
|
||||
yield 'custom scheme without slashes' => ['config:myapp/settings'];
|
||||
yield 'custom scheme with slashes' => ['config://myapp/settings'];
|
||||
}
|
||||
|
||||
public function testFromArrayValid(): void
|
||||
{
|
||||
$resource = Resource::fromArray([
|
||||
|
|
|
|||
Loading…
Reference in a new issue