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