8
8
[ ![ Sponsor development of this project] ( https://img.shields.io/badge/sponsor%20this%20package-%E2%9D%A4-ff69b4.svg?style=flat-square )] ( https://github.com/sponsors/nyamsprod )
9
9
10
10
` bakame/http-structured-fields ` is a framework-agnostic PHP library that allows you to parse, serialize
11
- build and update HTTP Structured Fields in PHP according to the [ RFC8941] ( https://www.rfc-editor.org/rfc/rfc8941.html ) .
11
+ create and update HTTP Structured Fields in PHP according to the [ RFC8941] ( https://www.rfc-editor.org/rfc/rfc8941.html ) .
12
12
13
13
Once installed you will be able to do the following:
14
14
@@ -24,20 +24,20 @@ $field[2]->parameter('q'); // returns (float) 0.9
24
24
$field[0]->value()->toString(); // returns 'text/html'
25
25
$field[0]->parameter('q'); // returns null
26
26
27
- //2 - building a Retrofit Cookie Header
28
- echo DataType::List->build ([
27
+ //2 - building a retrofit Cookie Header
28
+ echo DataType::List->serialize ([
29
29
[
30
30
['foo', 'bar'],
31
31
[
32
- ['expire', $expire ],
32
+ ['expire', new DateTimeImmutable('2023-04-14 20:32:08') ],
33
33
['path', '/'],
34
34
[ 'max-age', 2500],
35
35
['secure', true],
36
36
['httponly', true],
37
37
['samesite', Token::fromString('lax')],
38
38
]
39
39
],
40
- ]),
40
+ ]);
41
41
// returns ("foo" "bar");expire=@1681504328;path="/";max-age=2500;secure;httponly=?0;samesite=lax
42
42
```
43
43
@@ -58,9 +58,11 @@ composer require bakame/http-structured-fields
58
58
### Foreword
59
59
60
60
> [ !CAUTION]
61
- > While this package parses and serializes the header value, it does not validate its content.
62
- It is still required to validate the parsed data against the constraints of the corresponding
63
- header. Content validation is out of scope for this library.
61
+ > While this package parses and serializes the HTTP value, it does not validate its content
62
+ > against any conformance rule. You are still required to perform a compliance check
63
+ > against the constraints of the corresponding field. Content validation is
64
+ > out of scope for this library even though you can leverage some of its feature to
65
+ > ease the required validation.
64
66
65
67
### Parsing and Serializing Structured Fields
66
68
@@ -69,7 +71,7 @@ header. Content validation is out of scope for this library.
69
71
> [ !NOTE]
70
72
> New in version 1.2.0
71
73
72
- To quickly parse or build one of the five (5) available data type according to the RFC, you can use the ` DataType ` enum.
74
+ To quickly parse or serialize one of the five (5) available data type according to the RFC, you can use the ` DataType ` enum.
73
75
Apart from listing the data types (` List ` , ` InnerList ` , ` Parameters ` , ` Dictionary ` and ` Item ` ) you can give to
74
76
its ` parse ` method a string or a stringable object representing a field text representation. On success,
75
77
it will return an object representing the structured field otherwise an exception will be thrown.
@@ -81,14 +83,36 @@ $field->value(); // returns Token::fromString('bar); the found token va
81
83
$field->parameter('baz'); // returns 42; the value of the parameter or null if the parameter is not defined.
82
84
```
83
85
84
- On the other hand, ` build ` method expects an iterable structure composed of pair values
85
- that matches any structured field data type and returns its text representation.
86
+ To complement the behaviour, you can use its ` serialize ` method to turn an iterable structure
87
+ composed of pair values that matches any structured field data type and returns its
88
+ text representation.
89
+
90
+ ``` php
91
+ use Bakame\Http\StructuredFields\Item;
92
+ use Bakame\Http\StructuredFields\DataType;
93
+
94
+ echo DataType::List->serialize([
95
+ [
96
+ 'dumela lefatshe',
97
+ [['a', false]]
98
+ ],
99
+ [
100
+ ['a', 'b', Item::fromDateString('+30 minutes')],
101
+ [['a', true]]
102
+ ],
103
+ ]);
104
+ // display "dumela lefatshe";a=?0, ("a" "b" @1703319068);a
105
+ ```
106
+
107
+ The ` serialize ` method is a shortcut to converting the iterable structure into a ` StructuredField ` via
108
+ the ` create ` method and calling on the newly created object its ` toHttpValue ` method. With that
109
+ in mind, it is possible to rewrite The last example:
86
110
87
111
``` php
88
112
use Bakame\Http\StructuredFields\Item;
89
113
use Bakame\Http\StructuredFields\DataType;
90
114
91
- echo DataType::List->build ([
115
+ $list = DataType::List->create ([
92
116
[
93
117
'dumela lefatshe',
94
118
[['a', false]]
@@ -98,18 +122,20 @@ echo DataType::List->build([
98
122
[['a', true]]
99
123
],
100
124
]);
125
+
126
+ echo $list->toHttpValue();
101
127
// display "dumela lefatshe";a=?0, ("a" "b" @1703319068);a
102
128
```
103
129
104
130
> [ !TIP]
105
131
> While the format can be overwhelming at first, you will come to understand it while reading
106
132
> the rest of the documentation. Under the hood, the ` DataType ` enum uses the mechanism discussed hereafter.
107
133
108
- #### Using specific named constructor
134
+ #### Using specific data type classes
109
135
110
- The package provides specific classes for each data type. Parsing the structured field value is done
111
- via the ` fromHttpValue ` named constructor. The method is attached to each library's structured
112
- field representation as shown below :
136
+ The package provides specific classes for each data type. Parsing is done their respective
137
+ ` fromHttpValue ` named constructor. A example of how the method works can be seen below
138
+ using the ` Item ` class :
113
139
114
140
``` php
115
141
declare(strict_types=1);
@@ -127,9 +153,13 @@ $field->value(); // returns Token::fromString('bar); the found token va
127
153
$field->parameter('baz'); // returns 42; the value of the parameter or null if the parameter is not defined.
128
154
```
129
155
156
+ > [ !TIP]
157
+ > The ` DataType::parse ` method uses the ` fromHttpValue ` named constructor for
158
+ > each specific class to generate the structured field PHP representation.
159
+
130
160
The ` fromHttpValue ` method returns an instance which implements the ` StructuredField ` interface.
131
161
The interface provides the ` toHttpValue ` method that serializes it into a normalized RFC
132
- compliant HTTP field string value. To ease integration, the ` __toString ` method is
162
+ compliant HTTP field string value. To ease integration, the ` __toString ` method is
133
163
implemented as an alias to the ` toHttpValue ` method.
134
164
135
165
```` php
@@ -145,6 +175,10 @@ header('foo: '. $field->toHttpValue());
145
175
header('foo: '. $field);
146
176
````
147
177
178
+ > [ !TIP]
179
+ > This is the mechanism used by the ` DataType::serialize ` method. Once the Structured
180
+ > field has been created, the method calls its ` toHttpValue ` method.
181
+
148
182
All five (5) structured data type as defined in the RFC are provided inside the
149
183
` Bakame\Http\StructuredFields ` namespace. They all implement the
150
184
` StructuredField ` interface and expose a ` fromHttpValue ` named constructor:
@@ -155,65 +189,13 @@ All five (5) structured data type as defined in the RFC are provided inside the
155
189
- ` OuterList ` (named ` List ` in the RFC but renamed in the package because ` list ` is a reserved word in PHP.)
156
190
- ` InnerList `
157
191
158
- #### Advance parsing usage
159
-
160
- Starting with version ` 1.1 ` the internal parser has been made public in order to allow:
161
-
162
- - clearer decoupling between parsing and objet building
163
- - different parsers implementations
164
- - improve the package usage in testing.
165
-
166
- Each ` fromHttpValue ` method signature has been updated to take a second optional argument
167
- that represents the parser interface to use in order to allow parsing of the HTTP string
168
- representation value.
169
-
170
- By default, if no parser is provided, the package will default to use the package ` Parser ` class,
171
-
172
- ``` php
173
- Item::fromHttpValue(Stringable|string $httpValue, ItemParser $parser = new Parser()): Item;
174
- InnerList::fromHttpValue(Stringable|string $httpValue, InnerListParser $parser = new Parser()): InnerList;
175
- Dictionary::fromHttpValue(Stringable|string $httpValue, DictionaryParser $parser = new Parser()): Dictionary;
176
- OuterList::fromHttpValue(Stringable|string $httpValue, ListParser $parser = new Parser()): OuterList;
177
- Parameters::fromHttpValue(Stringable|string $httpValue, ParametersParser $parser = new Parser()): Parameters;
178
- ```
179
-
180
- The ` Parser ` class exposes the following method each belonging to a different contract or interface.
181
-
182
- ``` php
183
- Parser::parseValue(Stringable|string $httpValue): ByteSequence|Token|DateTimeImmutable|string|int|float|bool;
184
- Parser::parseItem(Stringable|string $httpValue): array;
185
- Parser::parseParameters(Stringable|string $httpValue): array;
186
- Parser::parseInnerList(Stringable|string $httpValue): array;
187
- Parser::parseList(Stringable|string $httpValue): array;
188
- Parser::parseDictionary(Stringable|string $httpValue): array;
189
- ```
190
-
191
- Once instantiated, calling one of the above listed method is straightforward:
192
-
193
- ``` php
194
- use Bakame\Http\StructuredFields\Parser;
195
-
196
- $parser = new Parser();
197
- $parser->parseValue('text/csv'); //returns Token::fromString('text/csv')
198
- $parser->parseItem('@1234567890;file=24');
199
- //returns an array
200
- // [
201
- // new DateTimeImmutable('@1234567890'),
202
- // ['file' => 24],
203
- // ]
204
- ```
205
-
206
- > [ !NOTE]
207
- > While the provided default ` Parser ` class implements all these methods you are free to only implement
208
- the methods you need.
209
-
210
192
### Accessing Structured Fields Values
211
193
212
194
#### RFC Value type
213
195
214
- Per the RFC, items can have different types that are translated to PHP using:
196
+ Per the RFC, items value can have different types that are translated to PHP using:
215
197
216
- - native type where possible
198
+ - native type or classes where possible;
217
199
- specific classes defined in the package namespace to represent non-native type
218
200
219
201
The table below summarizes the item value type.
@@ -231,13 +213,13 @@ The table below summarizes the item value type.
231
213
232
214
> [ !NOTE]
233
215
> The ` Date ` and ` DisplayString ` type are not yet part of any accepted
234
- > RFC. But they are already added as new types in the superseeding
216
+ > RFC. But they are already added as new types in the super-seeding
235
217
> RFC proposal.
236
218
>
237
219
> See https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-sfbis
238
220
> for more information.
239
221
240
- The Enum ` Type ` which list all available types can be used to determine the RFC type
222
+ The Enum ` Type ` list all available types and can be used to determine the RFC type
241
223
corresponding to a PHP structure using the ` Type::fromVariable ` static method.
242
224
The method will throw if the structure is not recognized. Alternatively
243
225
it is possible to use the ` Type::tryFromVariable ` which will instead
@@ -311,8 +293,8 @@ $displayString->type(); // returns Type::DisplayString
311
293
```
312
294
313
295
> [ !WARNING]
314
- > The classes DO NOT expose the ` Stringable ` interface to distinguish them
315
- > from a regular string or a string like object
296
+ > The classes DO NOT expose the ` Stringable ` interface to help distinguish
297
+ > them from a string or a stringable object
316
298
317
299
#### Item
318
300
@@ -406,7 +388,7 @@ use Bakame\Http\StructuredFields\ByteSequence;
406
388
use Bakame\Http\StructuredFields\Item;
407
389
use Bakame\Http\StructuredFields\Token;
408
390
409
- Item:new(DateTimeInterface|ByteSequence|Token|DisplayString|string|int|float|bool $value): self
391
+ Item:new(DateTimeInterface|ByteSequence|Token|DisplayString|string|int|array| float|bool $value): self
410
392
Item::fromDecodedByteSequence(Stringable|string $value): self;
411
393
Item::fromEncodedDisplayString(Stringable|string $value): self;
412
394
Item::fromDecodedDisplayString(Stringable|string $value): self;
@@ -674,7 +656,7 @@ $list = OuterList::fromPairs([
674
656
[
675
657
['foo', 'bar'],
676
658
[
677
- ['expire', $expire ],
659
+ ['expire', new DateTime('2024-01-01 12:33:45') ],
678
660
['path', '/'],
679
661
[ 'max-age', 2500],
680
662
['secure', true],
@@ -784,6 +766,58 @@ echo InnerList::new('foo', 'bar')
784
766
// ("foo" "bar");expire=@1681538756;path="/";max-age=2500
785
767
```
786
768
769
+ ### Advance parsing usage
770
+
771
+ Starting with version ` 1.1 ` the internal parser has been made public in order to allow:
772
+
773
+ - clearer decoupling between parsing and objet building
774
+ - different parsers implementations
775
+ - improve the package usage in testing.
776
+
777
+ Each ` fromHttpValue ` method signature has been updated to take a second optional argument
778
+ that represents the parser interface to use in order to allow parsing of the HTTP string
779
+ representation value.
780
+
781
+ By default, if no parser is provided, the package will default to use the package ` Parser ` class,
782
+
783
+ ``` php
784
+ Item::fromHttpValue(Stringable|string $httpValue, ItemParser $parser = new Parser()): Item;
785
+ InnerList::fromHttpValue(Stringable|string $httpValue, InnerListParser $parser = new Parser()): InnerList;
786
+ Dictionary::fromHttpValue(Stringable|string $httpValue, DictionaryParser $parser = new Parser()): Dictionary;
787
+ OuterList::fromHttpValue(Stringable|string $httpValue, ListParser $parser = new Parser()): OuterList;
788
+ Parameters::fromHttpValue(Stringable|string $httpValue, ParametersParser $parser = new Parser()): Parameters;
789
+ ```
790
+
791
+ The ` Parser ` class exposes the following method each belonging to a different contract or interface.
792
+
793
+ ``` php
794
+ Parser::parseValue(Stringable|string $httpValue): ByteSequence|Token|DateTimeImmutable|string|int|float|bool;
795
+ Parser::parseItem(Stringable|string $httpValue): array;
796
+ Parser::parseParameters(Stringable|string $httpValue): array;
797
+ Parser::parseInnerList(Stringable|string $httpValue): array;
798
+ Parser::parseList(Stringable|string $httpValue): array;
799
+ Parser::parseDictionary(Stringable|string $httpValue): array;
800
+ ```
801
+
802
+ Once instantiated, calling one of the above listed method is straightforward:
803
+
804
+ ``` php
805
+ use Bakame\Http\StructuredFields\Parser;
806
+
807
+ $parser = new Parser();
808
+ $parser->parseValue('text/csv'); //returns Token::fromString('text/csv')
809
+ $parser->parseItem('@1234567890;file=24');
810
+ //returns an array
811
+ // [
812
+ // new DateTimeImmutable('@1234567890'),
813
+ // ['file' => 24],
814
+ // ]
815
+ ```
816
+
817
+ > [ !NOTE]
818
+ > While the provided default ` Parser ` class implements all these methods you are free to only implement
819
+ the methods you need.
820
+
787
821
## Contributing
788
822
789
823
Contributions are welcome and will be fully credited. Please see [ CONTRIBUTING] ( .github/CONTRIBUTING.md ) and [ CODE OF CONDUCT] ( .github/CODE_OF_CONDUCT.md ) for details.
0 commit comments