Skip to content

Commit 7d457b3

Browse files
committed
Improve Date Type validation
1 parent f51fad0 commit 7d457b3

File tree

6 files changed

+61
-25
lines changed

6 files changed

+61
-25
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ All Notable changes to `bakame/http-strucured-fields` will be documented in this
77
### Added
88

99
- Support for `Stringable` instance added to `Item::from`, the instances will be converted to the string data type.
10-
- Support for the upcoming `Date` data type in `Item`. It is represented as a `DateTimeImmutable` object.
10+
- Support for the upcoming `Date` data type in `Item`. It is represented as a `DateTimeImmutable` object. (see https://httpwg.org/http-extensions/draft-ietf-httpbis-sfbis.html)
1111
- `ParameterAccess` interface updated with 3 new methods to ease parameter members modification.
1212
- `Parameter::create` named constructor to create a new instance without any parameter.
1313
- `Dictionnary::create` named constructor to create a new instance without any parameter.

src/InnerList.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,19 @@ public function parameters(): Parameters
6666
return clone $this->parameters;
6767
}
6868

69-
public function prependParameter(string $name, Item|ByteSequence|Token|DateTimeInterface|Stringable|bool|int|float|string $member): static
69+
public function prependParameter(string $key, Item|ByteSequence|Token|DateTimeInterface|Stringable|bool|int|float|string $member): static
7070
{
71-
return $this->withParameters($this->parameters()->prepend($name, $member));
71+
return $this->withParameters($this->parameters()->prepend($key, $member));
7272
}
7373

74-
public function appendParameter(string $name, Item|ByteSequence|Token|DateTimeInterface|Stringable|bool|int|float|string $member): static
74+
public function appendParameter(string $key, Item|ByteSequence|Token|DateTimeInterface|Stringable|bool|int|float|string $member): static
7575
{
76-
return $this->withParameters($this->parameters()->append($name, $member));
76+
return $this->withParameters($this->parameters()->append($key, $member));
7777
}
7878

79-
public function withoutParameter(string ...$name): static
79+
public function withoutParameter(string ...$keys): static
8080
{
81-
return $this->withParameters($this->parameters()->delete(...$name));
81+
return $this->withParameters($this->parameters()->delete(...$keys));
8282
}
8383

8484
public function withParameters(Parameters $parameters): static

src/Item.php

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -127,15 +127,31 @@ private static function filterString(Stringable|string $value): string
127127
*
128128
* @see https://www.rfc-editor.org/rfc/rfc8941.html#section-3.3.1
129129
*/
130-
private static function filterInteger(int $value): int
130+
private static function filterInteger(int $value, string $type): int
131131
{
132132
if ($value > 999_999_999_999_999 || $value < -999_999_999_999_999) {
133-
throw new SyntaxError('Integers are limited to 15 digits.');
133+
throw new SyntaxError($type.' are limited to 15 digits.');
134134
}
135135

136136
return $value;
137137
}
138138

139+
/**
140+
* Filter a date according to draft-ietf-httpbis-sfbis-latest.
141+
*
142+
* @see https://httpwg.org/http-extensions/draft-ietf-httpbis-sfbis.html#section-3.3.7
143+
*/
144+
private static function filterDate(DateTimeInterface $value): DateTimeImmutable
145+
{
146+
self::filterInteger($value->getTimestamp(), 'Date timestamp');
147+
148+
if ($value instanceof DateTimeImmutable) {
149+
return $value;
150+
}
151+
152+
return DateTimeImmutable::createFromInterface($value);
153+
}
154+
139155
/**
140156
* Returns a new instance from an HTTP Header or Trailer value string
141157
* in compliance with RFC8941.
@@ -339,19 +355,19 @@ public function parameters(): Parameters
339355
return clone $this->parameters;
340356
}
341357

342-
public function prependParameter(string $name, Item|ByteSequence|Token|DateTimeInterface|Stringable|bool|int|float|string $member): static
358+
public function prependParameter(string $key, Item|ByteSequence|Token|DateTimeInterface|Stringable|bool|int|float|string $member): static
343359
{
344-
return $this->withParameters($this->parameters()->prepend($name, $member));
360+
return $this->withParameters($this->parameters()->prepend($key, $member));
345361
}
346362

347-
public function appendParameter(string $name, Item|ByteSequence|Token|DateTimeInterface|Stringable|bool|int|float|string $member): static
363+
public function appendParameter(string $key, Item|ByteSequence|Token|DateTimeInterface|Stringable|bool|int|float|string $member): static
348364
{
349-
return $this->withParameters($this->parameters()->append($name, $member));
365+
return $this->withParameters($this->parameters()->append($key, $member));
350366
}
351367

352-
public function withoutParameter(string ...$name): static
368+
public function withoutParameter(string ...$keys): static
353369
{
354-
return $this->withParameters($this->parameters()->delete(...$name));
370+
return $this->withParameters($this->parameters()->delete(...$keys));
355371
}
356372

357373
public function withParameters(Parameters $parameters): static
@@ -419,11 +435,10 @@ public function isDate(): bool
419435
private static function filterValue(float|bool|int|string|Token|ByteSequence|DateTimeInterface|Stringable $value): ByteSequence|DateTimeImmutable|Token|string|int|bool|float
420436
{
421437
return match (true) {
422-
is_int($value) => self::filterInteger($value),
438+
is_int($value) => self::filterInteger($value, 'Integer'),
423439
is_float($value) => self::filterDecimal($value),
424440
is_string($value) || $value instanceof Stringable => self::filterString($value),
425-
$value instanceof DateTimeImmutable => $value,
426-
$value instanceof DateTimeInterface => DateTimeImmutable::createFromInterface($value),
441+
$value instanceof DateTimeInterface => self::filterDate($value),
427442
default => $value,
428443
};
429444
}

src/ItemTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,22 @@ public function it_fails_to_instantiate_an_invalid_date_format(): void
102102
Item::fromHttpValue('@112345.678');
103103
}
104104

105+
/** @test */
106+
public function it_fails_to_instantiate_an_out_of_range_date_in_the_future(): void
107+
{
108+
$this->expectException(SyntaxError::class);
109+
110+
Item::from(new DateTime('@'. 1_000_000_000_000_000));
111+
}
112+
113+
/** @test */
114+
public function it_fails_to_instantiate_an_out_of_range_date_in_the_past(): void
115+
{
116+
$this->expectException(SyntaxError::class);
117+
118+
Item::from(new DateTime('@'.-1_000_000_000_000_000));
119+
}
120+
105121
/** @test */
106122
public function it_instantiates_a_binary(): void
107123
{

src/ParameterAccess.php

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44

55
namespace Bakame\Http\StructuredFields;
66

7-
use DateTimeInterface;
8-
use Stringable;
9-
107
interface ParameterAccess
118
{
129
/**
@@ -22,7 +19,7 @@ public function parameters(): Parameters;
2219
*
2320
* @throws SyntaxError If the string key is not a valid
2421
*/
25-
public function prependParameter(string $name, Item|ByteSequence|Token|DateTimeInterface|Stringable|bool|int|float|string $member): static;
22+
public function prependParameter(string $key, Item $member): static;
2623

2724
/**
2825
* Adds a member at the end of the associated parameter instance and deletes any previous reference to the key if present.
@@ -32,15 +29,15 @@ public function prependParameter(string $name, Item|ByteSequence|Token|DateTimeI
3229
*
3330
* @throws SyntaxError If the string key is not a valid
3431
*/
35-
public function appendParameter(string $name, Item|ByteSequence|Token|DateTimeInterface|Stringable|bool|int|float|string $member): static;
32+
public function appendParameter(string $key, Item $member): static;
3633

3734
/**
3835
* Deletes members associated with the list of submitted keys in the associated parameter intance.
3936
*
4037
* This method MUST retain the state of the current instance, and return
4138
* an instance that contains the specified parameter change.
4239
*/
43-
public function withoutParameter(string ...$name): static;
40+
public function withoutParameter(string ...$keys): static;
4441

4542
/**
4643
* Returns a new instance with the newly associated parameter instance.

src/ParserTest.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,21 @@ public function it_parse_a_date_item(): void
4949
}
5050

5151
/** @test */
52-
public function it_will_fail_with_wrong_date(): void
52+
public function it_will_fail_with_wrong_date_format(): void
5353
{
5454
$this->expectException(SyntaxError::class);
5555

5656
Parser::parseDictionary('a=@12345.678');
5757
}
5858

59+
/** @test */
60+
public function it_will_fail_with_out_of_range_date_format(): void
61+
{
62+
$this->expectException(SyntaxError::class);
63+
64+
Parser::parseDictionary('a=@'. 1_000_000_000_000_000);
65+
}
66+
5967
/** @test */
6068
public function it_will_fail_with_wrong_string(): void
6169
{

0 commit comments

Comments
 (0)