Usage
At the heart of this package is a Factory
that is able to generate ETag
instances, for arbitrary content, as well as to parse strings that contain etag values and turn them into a collection of etags instances.
Obtain Factory
To obtain the Factory
instance, use the ETagGeneratorFactoryTrait
in your components.
use Aedart\ETags\Traits\ETagGeneratorFactoryTrait;
class UsersController
{
use ETagGeneratorFactoryTrait;
public function index()
{
$factory = $this->getEtagGeneratorFactory();
// ..remaining not shown...
}
}
Generator
Before you are able to create a new ETag
instance, you must first obtain a Generator
. This can be done via the profile()
method in the Factory
.
$generator = $factory->profile(); // Default profile
To obtain a Generator
for a different profile, simply specify the profile's name as argument.
$generator = $factory->profile('my-custom-profile');
For more information, see Generator documentation.
Make an Etag
Once you have your desired Etag Generator
instance, use the make()
method to create a new ETag
instance of some content. The method accepts two arguments:
$content
:mixed
: arbitrary content$weak
:bool
: optional, defaulttrue
Weak vs. Strong
If $weak
is set to true, the created ETag
is flagged as "weak" and therefore indented to be used for "weak comparison" (E.g. If-None-Match
Http header comparison).
Otherwise, when $weak
is set to false, the ETag
is not flagged as "weak". Thus, the etag is then intended to be used for "strong comparison" (E.g. If-Match
Http header comparison).
For additional information, see RFC9110.
$etag = $generator->make('my-content', true);
echo (string) $etag; // E.g. W/"ab416j5"
For the sake of convenience, you can use the shortcut methods makeWeak()
and makeStrong()
to achieve the same.
$weakEtag = $generator->makeWeak('my-content');
$strongEtag = $generator->makeStrong('my-content');
echo (string) $weakEtag; // E.g. W/"ab416j5"
echo (string) $strongEtag; // E.g. "4720b076892bb2fb65e75af902273c73a2967e4a"
Using Facade
This package also comes with a Facade, that allows you to achieve the same as previously shown.
Create new Etags
To make new etags, simply invoke the make()
, makeWeak()
or makeStrong()
methods on the facade.
use Aedart\ETags\Facades\Generator;
$weakEtag = Generator::makeWeak('my-content');
$strongEtag = Generator::makeStrong('my-content');
Use different profile
Unless otherwise specified, the "default" generator "profile" is used by the facade, when creating new etag instances. To use a different profile, specify the desired name via the profile()
method.
$etag = Generator::profile('my-custom-profile')->make('my-content');
Parsing
When you need to create ETag instance from string values, e.g. Http headers, then you can use the parse()
method, in the Factory
. The method will attempt to parse given etag values and create a collection with corresponding ETag
instances.
// Via the factory
$collection = $factory->parse('W/"15487", W/"r2d23574", W/"c3pio784"');
// ...Or via the Facade
$collection = Generator::parse('W/"15487", W/"r2d23574", W/"c3pio784"');
If you only desire to parse a single value, then use the parseSingle()
which will return a single ETag
instance.
// Via the factory
$etag = $factory->parseSingle('W/"15487"');
// ...Or via the Facade
$etag = Generator::parseSingle('W/"15487"');
Caution
Both parse()
and parseSingle()
will throw an ETagException
, if unable to parse given string value.
For instance, if you try to parse a list of value that contain a wildcard (*
), then it is considered syntactically invalid (acc. to RFC9110). An exception will therefore be thrown.
// Throws exception ... invalid list of etag values!
$collection = Generator::parse('*, W/"r2d23574", W/"c3pio784"');
$etag = Generator::parseSingle('my-invalid-etag-value');
// ---------------------------------------------------------------- //
// Valid
$collection = Generator::parse('*');
// ...Or parse single
$etag = Generator::parseSingle('*');
echo $etag->isWildcard(); // true
Comparison
You have the following two comparison options, when you want to compare etags:
- strong comparison: two entity tags are equivalent if both are not weak and their opaque-tags match character-by-character (source RFC-9110).
- weak comparison: two entity tags are equivalent if their opaque-tags match character-by-character, regardless of either or both being tagged as "weak" (source RFC-9110).
Please read RFC-9110's description of If-Match
, If-None-Match
Http headers, and how the comparison works to understand the difference and when to use either of the comparison methods.
Strong vs. Weak Comparison
The herein shown examples do not necessarily represent correct usage of the comparison for http headers.To clarify when to use "weak" or "strong" comparison, consider the following:
If-Match
: "[...] An origin server MUST use the strong comparison function when comparing entity tags for If-Match [...]" (source RFC-9110)
If-None-Match
: "[...] A recipient MUST use the weak comparison function when comparing entity tags for If-None-Match [...]" (source RFC-9110)
Via Collection
When you have a collection of etag instances, you can match a single ETag
(or value) against the etags in the collection. The contains()
method allows you to do so.
$collection = Generator::parse('W/"15487", W/"r2d23574", W/"c3pio784"');
$etag = Generator::makeWeak($content); // E.g. W/"c3pio784"
echo $collection->contains($etag, true); // false - strong comparison
echo $collection->contains($etag); // true - weak comparison
You may also compare against a string etag value directly.
echo $collection->contains('W/"c3pio784"', true); // false - strong comparison
echo $collection->contains('W/"c3pio784"'); // true - weak comparison
Via ETag
To compare two ETag
instances against each other, use the matches()
method.
$etagA = Generator::parseSingle('W/"r2d23574"');
$etagB = Generator::makeWeak($content); // E.g. W/"r2d23574"
echo $etagA->matches($etagB, true); // false - strong comparison
echo $etagA->matches($etagB); // true - weak comparison
Wildcard
A wildcard (*
) is a valid etag value for both If-Match
and If-None-Match
Http headers. When comparing against a wildcard, the result will always be true
if you have an ETag
or etag value to compare against, regardless whether you use "weak" or "strong" comparison.
$collection = Generator::parse('*');
echo $collection->contains('W/"c3pio784"', true); // true - strong comparison
echo $collection->contains('W/"c3pio784"'); // true - weak comparison
// -------------------------------------------------------------------------- //
$etagA = Generator::parseSingle('*');
$etagB = Generator::makeWeak($content); // E.g. W/"15487"
echo $collection->contains($etag, true); // true - strong comparison
echo $collection->contains($etag); // true - weak comparison