Files
coolify/tests/Feature/ApiRateLimitClientIpTest.php
T
2026-10-27 20:25:53 +01:00

57 lines
1.9 KiB
PHP

<?php
use App\Models\InstanceSettings;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Testing\TestResponse;
uses(RefreshDatabase::class);
beforeEach(function () {
config()->set('app.maintenance.store', 'array');
config()->set('api.rate_limit', 2);
InstanceSettings::forceCreate(['id' => 0]);
});
function pushSentinelFrom(string $clientIp, string $peer = '172.70.0.1'): TestResponse
{
return test()
->withHeader('CF-Connecting-IP', $clientIp)
->withServerVariables(['REMOTE_ADDR' => $peer])
->postJson('/api/v1/sentinel/push');
}
it('gives each Cloudflare client ip its own sentinel push bucket on cloud', function () {
config()->set('constants.coolify.self_hosted', false);
pushSentinelFrom('203.0.113.10')->assertUnauthorized();
pushSentinelFrom('203.0.113.10')->assertUnauthorized();
pushSentinelFrom('203.0.113.10')->assertStatus(429);
pushSentinelFrom('203.0.113.20')->assertUnauthorized();
});
it('ignores the Cloudflare client ip for sentinel pushes on self-hosted instances when the peer is not Cloudflare', function () {
config()->set('constants.coolify.self_hosted', true);
pushSentinelFrom('203.0.113.10', peer: '198.51.100.7')->assertUnauthorized();
pushSentinelFrom('203.0.113.10', peer: '198.51.100.7')->assertUnauthorized();
pushSentinelFrom('203.0.113.20', peer: '198.51.100.7')->assertStatus(429);
});
it('keys unauthenticated limiters by the Cloudflare client ip on cloud', function (string $limiter) {
config()->set('constants.coolify.self_hosted', false);
$request = Request::create('/', server: [
'REMOTE_ADDR' => '172.70.0.1',
'HTTP_CF_CONNECTING_IP' => '203.0.113.10',
]);
$limit = RateLimiter::limiter($limiter)($request);
expect($limit->key)->toBe('203.0.113.10');
})->with(['api', '5', 'feedback']);