Skip to content

v2.11.1

Choose a tag to compare

@sean-e-dietrich sean-e-dietrich released this 30 Jul 23:55
104180f

One fix, for a defect introduced by v2.11.0's user-agent caching.

If your logs show the UserAgent plugin working normally but the site feels slow, this release is why you could not see the cause. An unwritable cache directory made every request re-parse the full detection corpus — roughly 645 ms instead of ~20 ms — while the only log line reported the cache as successfully initialised.

No configuration changes. No behaviour changes to detection, rules, or anything else.

PHP 8.1–8.5 supported.

Fixes

  • The user-agent cache is now verified before it is trusted.

    Constructing a cache pool proves nothing. Symfony's FilesystemAdapter is created quite happily against a directory it cannot write to, and only fails later, on each individual write. v2.11.0 took successful construction as success, logged

    [DEBUG] User Agent regex cache initialized
    

    and then re-parsed the 1.7 MB detection corpus on every single request, indefinitely, with nothing above debug to say so.

    The plugin now writes and reads back a probe value before trusting a pool. When that value does not come back:

    [WARNING] User Agent regex cache is not writable - every request will
              re-parse the detection corpus
    

    The context carries the impact and the three ways out. Falling back to running uncached is still the right behaviour — an optimisation must not be able to take a site down — but it has to be visible. A 30× slowdown that reports itself as healthy is worse than one that reports nothing at all.

    A round trip rather than an is_writable() check, deliberately: the pool may be a filesystem directory, Redis, APCu, or an instance injected through configuration overrides, and the only property that matters is whether a value written now can be read back. It costs a fraction of a millisecond and runs once per plugin instance, not once per evaluation.

Who is affected

Anyone on v2.11.0 whose cache location is not writable by the PHP user. That is not an exotic situation — a read-only container filesystem, a KANOPI_FIREWALL_CACHE_DIR owned by the deploying user rather than the web user, or an open_basedir that excludes the system temp directory all produce it.

If the cache is writable, v2.11.0 was already behaving correctly and this release changes nothing for you.

To check without upgrading, look for User Agent regex cache initialized at debug and confirm the directory it names actually contains files after a request.

Upgrade notes

  • composer update kanopi/firewall, and nothing else. No config to change, no new dependencies, no rule behaviour altered.

  • After upgrading, check your logs once at warning level. If the new message appears, the cache has never been working and the fix has simply made that visible. Point metadata.cache.dir at a writable directory, define KANOPI_FIREWALL_CACHE_DIR, or set metadata.cache: false to accept the cost deliberately and silence it.

  • Nothing needs clearing. device-detector keys its cache entries by its own version, so upgrades invalidate them without help.

Internal

  • Three regression tests: the unwritable case, that the probe does not reject a cache which works, and that the probe leaves nothing behind that could be mistaken for corpus data.

  • Suite: 1,015 unit tests and 49 integration tests pass. PHPCS, PHPStan at level max and Rector are clean, and bin/firewall-check is clean at level max despite sitting outside the src/-scoped gates. The 2 reported deprecations are a pre-existing ReflectionProperty::setValue() call in LoggingFactoryTest, unrelated to this release.

  • ConfigTest::testFileGetContentsSuccessSameProcess reaches https://example.com and is flaky on a cold network. It failed once during this work and passes in isolation; it is unrelated to the fix, but worth knowing if CI trips on it.