Deprecate KeyExtractors::ip() and drop its usages#106
Merged
Conversation
The resolved client IP is the default for every rule (omit the key / keyIp()), so KeyExtractors::ip() (raw REMOTE_ADDR) is @deprecated; the raw peer is read via getServerParams()['REMOTE_ADDR']. Inline the REMOTE_ADDR fallback at the former internal call sites (Config::clientIpResolver, the IP-aware matchers' standalone match(), InfrastructureBanListener), drop the dead portable 'ip' compile arm, and migrate examples and tests to keyless rules. Only ip()'s own unit tests reference it.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR deprecates KeyExtractors::ip() (raw REMOTE_ADDR) and removes its internal usages by making “keyless rules” the default way to key on the resolved client IP (via the Config IP resolver, falling back to REMOTE_ADDR).
Changes:
- Remove
KeyExtractors::ip()usage across matchers/listeners and inline aREMOTE_ADDRfallback resolver at those call sites. - Drop the portable key compile arm for
{type: 'ip'}(now materializes keyless viacompileKeyExtractor()). - Migrate examples and tests to omit the rule key (defaulting to the client IP resolver).
Reviewed changes
Copilot reviewed 34 out of 34 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Unit/Store/PdoCacheFunctionalTest.php | Updates throttle/fail2ban setup to omit explicit IP keying. |
| tests/Unit/RequestAttributeIntegrationTest.php | Migrates fail2ban rules to rely on default client-IP keying. |
| tests/Unit/Config/ConfigCompositionTest.php | Adjusts composed typed rules to use null key extractors (keyless). |
| tests/phpt/track/track_threshold_flag.phpt | Removes explicit KeyExtractors::ip() from track config. |
| tests/phpt/throttle/throttle_sliding_window_allows_then_429.phpt | Removes explicit IP key from sliding throttle usage. |
| tests/phpt/throttle/throttle_multi_window_burst_blocks.phpt | Removes explicit IP key from multi-window throttle usage. |
| tests/phpt/throttle/throttle_fixed_window_allows_then_429.phpt | Removes explicit IP key from fixed-window throttle usage. |
| tests/phpt/throttle/throttle_dynamic_limit_by_header.phpt | Removes explicit IP key from dynamic throttle usage. |
| tests/phpt/fail2ban/fail2ban_threshold_then_ban.phpt | Removes explicit IP key from fail2ban config. |
| tests/phpt/context/request_context_fail2ban_signal.phpt | Removes explicit IP key from fail2ban context test config. |
| tests/phpt/allow2ban/allow2ban_threshold_then_ban.phpt | Removes explicit IP key from allow2ban config. |
| src/Portable/PortableConfig.php | Removes dead 'ip' arm from key compilation (ip handled as keyless elsewhere). |
| src/Pattern/SnapshotBlocklistMatcher.php | Replaces KeyExtractors::ip() fallback with inline REMOTE_ADDR resolver. |
| src/Matchers/TrustedBotMatcher.php | Replaces KeyExtractors::ip() fallback with inline REMOTE_ADDR resolver + doc tweak. |
| src/Matchers/IpMatcher.php | Replaces KeyExtractors::ip() fallback with inline REMOTE_ADDR resolver + doc tweak. |
| src/KeyExtractors.php | Marks ip() deprecated and clarifies intended usage in docblock. |
| src/Infrastructure/InfrastructureBanListener.php | Replaces default KeyExtractors::ip() with inline REMOTE_ADDR resolver + doc tweak. |
| src/Config/FileIpBlocklistMatcher.php | Replaces KeyExtractors::ip() fallback with inline REMOTE_ADDR resolver + doc tweak. |
| src/Config.php | Changes clientIpResolver() fallback from KeyExtractors::ip() to inline REMOTE_ADDR resolver. |
| README.md | Updates proxy/IP guidance to recommend reading REMOTE_ADDR directly for raw peer. |
| examples/27-request-context.php | Updates example fail2ban rule to omit explicit key extractor. |
| examples/26-psr17-factories.php | Updates throttle examples to omit explicit key extractor. |
| examples/24-pdo-storage.php | Updates throttle/fail2ban examples to omit explicit key extractor. |
| examples/22-multi-throttle.php | Updates multi-throttle example to omit explicit key extractor. |
| examples/21-sliding-window.php | Updates sliding throttle example to omit explicit key extractor. |
| examples/16-allow2ban.php | Updates allow2ban example to omit explicit key extractor. |
| examples/11-redis-storage.php | Updates throttle/fail2ban examples to omit explicit key extractor. |
| examples/10-observability-opentelemetry.php | Updates throttle example to omit explicit key extractor. |
| examples/09-observability-monolog.php | Updates throttle example to omit explicit key extractor. |
| examples/06-bot-detection.php | Updates fail2ban/throttle examples to omit explicit key extractor. |
| examples/03-api-rate-limiting.php | Updates throttle examples to omit explicit key extractor. |
| examples/02-brute-force-protection.php | Updates fail2ban example to omit explicit key extractor. |
| examples/01-basic-setup.php | Updates throttle example to omit explicit key extractor. |
| CHANGELOG.md | Adds deprecation note for KeyExtractors::ip() and updates related guidance. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
KeyExtractors (namespace Flowd\Phirewall) does not import PortableConfig, so the bare PortableConfig::keyIp() docblock references resolved to the non-existent Flowd\Phirewall\PortableConfig for IDE/doc tooling. Use the FQCN.
Drop the ip() rule keys in the quick-start, API-rate-limiting and login examples (keyless now keys on the resolved client IP), remove the imports that become unused, and use $request in the raw-REMOTE_ADDR prose.
Comment on lines
221
to
+223
| When no resolver is set the client IP is `REMOTE_ADDR`. For the raw connecting peer | ||
| address regardless of proxy configuration, use `KeyExtractors::ip()`. | ||
| address regardless of proxy configuration, read `$request->getServerParams()['REMOTE_ADDR']` | ||
| directly. |
|
|
||
| - **`KeyExtractors::clientIp(TrustedProxyResolver)`** - the resolved client IP is now the default discriminator for every rule via the `Config` IP resolver, so a dedicated key extractor is no longer needed. Configure proxy trust once with `$config->setIpResolver($trustedProxyResolver->resolve(...))` and omit the rule's key (or use `PortableConfig::keyIp()`); both resolve the client IP. For the raw connecting peer address, `KeyExtractors::ip()` (REMOTE_ADDR) remains the explicit escape hatch. | ||
| - **`KeyExtractors::clientIp(TrustedProxyResolver)`** - the resolved client IP is now the default discriminator for every rule via the `Config` IP resolver, so a dedicated key extractor is no longer needed. Configure proxy trust once with `$config->setIpResolver($trustedProxyResolver->resolve(...))` and omit the rule's key (or use `PortableConfig::keyIp()`); both resolve the client IP. | ||
| - **`KeyExtractors::ip()`** - the name is ambiguous (it reads like "the client IP" but returns the raw `REMOTE_ADDR` peer, which behind a proxy is the proxy itself) and it bypasses the `Config` IP resolver. To key on the client IP, omit the rule's key (or use `PortableConfig::keyIp()`) so it resolves through the resolver. For the raw connecting peer, read `$request->getServerParams()['REMOTE_ADDR']` directly. |
Comment on lines
+25
to
+28
| * @deprecated The name is ambiguous and it bypasses the Config IP resolver. To key on | ||
| * the client IP, omit the rule's key (or use \Flowd\Phirewall\Portable\PortableConfig::keyIp()) so it resolves | ||
| * through the Config's IP resolver (else REMOTE_ADDR). For the raw connecting peer, | ||
| * read $request->getServerParams()['REMOTE_ADDR'] directly. |
Comment on lines
+377
to
+380
| return $this->ipResolver ?? static function (ServerRequestInterface $serverRequest): ?string { | ||
| $remoteAddr = $serverRequest->getServerParams()['REMOTE_ADDR'] ?? null; | ||
| return is_string($remoteAddr) && $remoteAddr !== '' ? $remoteAddr : null; | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The resolved client IP is the default for every rule (omit the key / keyIp()), so KeyExtractors::ip() (raw REMOTE_ADDR) is
@deprecated; the raw peer is read via getServerParams()['REMOTE_ADDR']. Inline the REMOTE_ADDR fallback at the former internal call sites (Config::clientIpResolver, the IP-aware matchers' standalone match(), InfrastructureBanListener), drop the dead portable 'ip' compile arm, and migrate examples and tests to keyless rules. Only ip()'s own unit tests reference it.