utopia-php / waf
Lite and extensible Web Application Firewall rules management library for the Utopia PHP ecosystem.
Requires
- php: >=8.5
- utopia-php/validators: ^1.0
Requires (Dev)
- laravel/pint: ^1.18
- phpstan/phpstan: ^1.11
- phpunit/phpunit: ^11.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- 0.1.2
- 0.1.1
- 0.1.0
- 0.0.9
- 0.0.8
- 0.0.7
- 0.0.6
- 0.0.5
- 0.0.4
- 0.0.3
- 0.0.2
- 0.0.1
- dev-feat/headers-rule
- dev-chore/validators-1.0
- dev-chore/validators-0.5
- dev-feat-custom-attribute-type
- dev-new-waf-challenge-type
- dev-feat-cidr-conditions
- dev-validators-downgrade
- dev-feat-case-insensitive-conditions
- dev-fix/validators-0.3
- dev-feat-challenge-pow
- dev-dev
This package is auto-updated.
Last update: 2026-10-07 09:35:25 UTC
README
Important
This repository is a read-only mirror of packages/waf in Appwrite's private Cloud repository (appwrite-labs/cloud). Development happens there, so pull requests and issues opened here are closed automatically.
Lite & fast micro PHP Web Application Firewall (WAF) rules management library that is easy to use and fits naturally inside the Utopia ecosystem.
The library ships with:
- A
Conditionbuilder that mirrors the API ofUtopia\Database\Query, including JSON parsing helpers and logical operators. - Action specific rule classes (
Bypass,Deny,Challenge,RateLimit,Redirect). - A dependency-free
Firewallorchestrator that evaluates rules against any set of request attributes.
Installation
composer require utopia-php/waf
Usage
<?php require_once __DIR__ . '/vendor/autoload.php'; use Utopia\WAF\Condition; use Utopia\WAF\Firewall; use Utopia\WAF\Rules\Bypass; use Utopia\WAF\Rules\Deny; use Utopia\WAF\Rules\Challenge; use Utopia\WAF\Rules\RateLimit; use Utopia\WAF\Rules\Redirect; $firewall = new Firewall(); $firewall->setAttribute('requestIP', '127.0.0.1'); $firewall->setAttribute('requestMethod', 'GET'); $firewall->setAttribute('requestPath', '/index'); $firewall->setAttribute('headers', [ 'X-Country' => 'US', ]); $firewall->addRule(new Deny([ Condition::equal('ip', ['127.0.0.1']), Condition::notEqual('path', '/status'), ])); $firewall->addRule(new Bypass([ Condition::equal('country', ['US']), Condition::equal('method', ['GET']), ])); $firewall->addRule(new Challenge([ Condition::startsWith('path', '/admin'), ], Challenge::TYPE_CAPTCHA)); $firewall->addRule(new RateLimit([ Condition::equal('method', ['POST']), ], limit: 100, interval: 3600)); $firewall->addRule(new Redirect([ Condition::startsWith('path', '/legacy'), ], location: '/new-home', statusCode: 301)); var_dump($firewall->verify()); // bool(true|false) if ($rule = $firewall->getLastMatchedRule()) { echo 'Matched action: ' . $rule->getAction(); }
Building Conditions
Conditions can be created fluently or by encoding/decoding JSON definitions:
$condition = Condition::and([ Condition::equal('ip', ['10.0.0.1']), Condition::notEqual('path', '/health'), ]); $json = $condition->encode(); $parsed = Condition::decode($json);
Available operators mirror the database query builder: equal, notEqual, lessThan, greaterThan, contains, between, startsWith, endsWith, isNull, and, or, and more.
Rate Limiting
RateLimit rules only store the metadata required for external throttling (limit + interval). Once a rate limit rule matches, the firewall returns true and exposes the matched rule via getLastMatchedRule() so you can call any third-party rate limiter with the provided metadata.
$firewall->addRule(new RateLimit([ Condition::equal('ip', ['203.0.113.12']), ], limit: 500, interval: 60)); if ($firewall->verify()) { $matched = $firewall->getLastMatchedRule(); if ($matched instanceof RateLimit) { // Invoke your preferred rate limiter here using $matched->getLimit() and $matched->getInterval() } }
Testing Locally
The package is developed in packages/waf of appwrite-labs/cloud, which supplies PHPUnit, Pint, PHPStan and Rector. From that repository's root:
bin/monorepo test waf # unit tests bin/monorepo check waf --fix # Pint, PHPStan, Rector
On a standalone checkout of this mirror, the manifest no longer pulls in PHPUnit, so add it first:
composer install
composer require --dev phpunit/phpunit:^12
composer test
License
MIT