Ontwikkel een PHP-script voor geautomatiseerde API rate limiting
description
Met deze prompt leer je hoe je API-verzoeken effectief kunt beperken om overbelasting en misbruik te voorkomen. Het biedt praktische oplossingen voor het instellen van limieten en het beheren van gebruikersverzoeken, wat de stabiliteit en veiligheid van je PHP-applicaties verhoogt.
prompt
Help me een PHP-script te ontwikkelen dat API rate limiting implementeert om het aantal verzoeken per gebruiker of IP-adres te beperken binnen een bepaalde tijdsperiode. Leg uit hoe ik limieten kan instellen, verzoeken kan tellen, en gebruikers kan blokkeren of vertragen bi ...
try_prompt
generate_helper
disclaimerOnPageApi
tags
ai_answers
provider: openai
model: gpt-4.1-nano
Hier is een basis PHP-script dat API rate limiting implementeert met Redis als opslag voor de tellers. Ik leg ook uit hoe je limieten instelt, verzoeken telt en gebruikers blokkeert of vertraagt bij overschrijding.
### 1. Vereisten
- PHP met Redis-extensie geïnstalleerd (`php-redis`)
- Een draaiende Redis-server
### 2. Instellingen
- Limiet: 100 verzoeken per uur
- Tijdsperiode: 3600 seconden (1 uur)
### 3. PHP-script
```php
<?php
// Verbinding maken met Redis
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// Instellingen
$limiet = 100; // maximaal aantal verzoeken
$periode = 3600; // periode in seconden (1 uur)
// Haal IP-adres van de gebruiker
$ip = $_SERVER['REMOTE_ADDR'];
// Sleutel voor Redis
$sleutel = "api_rate_limit:" . $ip;
// Functie om verzoek te tellen en limieten te controleren
function checkRateLimit($redis, $sleutel, $limiet, $periode) {
// Kijk of er al een teller bestaat
$aantal = $redis->get($sleutel);
if ($aantal === false) {
// Geen teller gevonden, initialiseer en zet vervaltijd
$redis->set($sleutel, 1, $periode);
return true; // toegang toegestaan
} else {
// Teller bestaat, verhoog deze
$aantal = (int)$aantal + 1;
if ($aantal > $limiet) {
// Limiet overschreden
return false; // toegang geweigerd
} else {
// Verhoog teller zonder vervaltijd opnieuw te zetten
$redis->incr($sleutel);
return true; // toegang toegestaan
}
}
}
// Controle
if (checkRateLimit($redis, $sleutel, $limiet, $periode)) {
// Toegang toegestaan
echo "Verzoek toegestaan.";
// Hier verdere verwerking van de API-aanvraag
} else {
// Limiet overschreden, gebruiker blokkeren of vertragen
// Optie 1: Gebruiker blokkeren
http_response_code(429); // Too Many Requests
echo "Limiet overschreden. Probeer het later opnieuw.";
exit;
}
?>
```
### 4. Uitleg
- **Limiet instellen:** `$limiet = 100;` en `$periode = 3600;` bepalen respectievelijk het maximale aantal verzoeken en de tijdsperiode.
- **Verzoeken tellen:** De functie `checkRateLimit()` controleert of de teller bestaat, maakt deze aan indien nodig, en verhoogt deze bij elk verzoek.
- **Gebruiker blokkeren:** Bij overschrijding wordt een HTTP 429 statuscode gestuurd en wordt verdere verwerking gestopt.
- **Opslag:** Redis wordt gebruikt om de tellers te bewaren en te resetten na de ingestelde periode.
### 5. Optioneel: Vertraagde responses
In plaats van blokkeren, kan je ook een vertraging invoegen of de gebruiker laten wachten, bijvoorbeeld door `sleep()` of door de response te vertragen.
---
Als je nog verdere aanpassingen of uitleg nodig hebt, laat het gerust weten!
provider: deepseek
model: deepseek-chat
Hier is een PHP-implementatie voor rate limiting met Redis:
```php
<?php
class RateLimiter {
private $redis;
private $limit;
private $window;
public function __construct($limit = 100, $window = 3600) {
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
$this->limit = $limit;
$this->window = $window;
}
public function checkLimit($identifier) {
$key = "ratelimit:{$identifier}";
$current = time();
// Verwijder oude timestamps buiten het tijdvenster
$this->redis->zRemRangeByScore($key, 0, $current - $this->window);
// Tel huidige verzoeken in het venster
$count = $this->redis->zCard($key);
if ($count < $this->limit) {
// Voeg huidig verzoek toe
$this->redis->zAdd($key, $current, $current);
// Stel TTL in voor automatische opschoning
$this->redis->expire($key, $this->window);
return [
'allowed' => true,
'remaining' => $this->limit - $count - 1,
'reset' => $current + $this->window
];
}
return [
'allowed' => false,
'remaining' => 0,
'reset' => $this->redis->zRange($key, 0, 0, true)[0] + $this->window
];
}
public function getClientIdentifier() {
// Gebruik IP-adres als identifier (kan worden uitgebreid met user ID)
return $_SERVER['REMOTE_ADDR'];
}
}
// Gebruiksvoorbeeld
$limiter = new RateLimiter(100, 3600);
$identifier = $limiter->getClientIdentifier();
$result = $limiter->checkLimit($identifier);
if (!$result['allowed']) {
http_response_code(429);
header('Retry-After: ' . ($result['reset'] - time()));
echo 'Te veel verzoeken. Probeer opnieuw over ' . ($result['reset'] - time()) . ' seconden.';
exit;
}
// Verwerk normaal verzoek
echo "Verzoek toegestaan. Nog " . $result['remaining'] . " verzoeken over dit uur.";
?>
```
## Uitleg van de implementatie:
### 1. **Limieten instellen**
- `$limit = 100`: Maximum aantal verzoeken per tijdvenster
- `$window = 3600`: Tijdvenster in seconden (1 uur)
### 2. **Verzoeken tellen met Redis**
- Gebruik Redis sorted sets met timestamps als scores
- `zRemRangeByScore()` verwijdert oude verzoeken buiten het tijdvenster
- `zCard()` telt huidige verzoeken binnen het venster
- `zAdd()` voegt nieuw verzoek toe met huidige timestamp
### 3. **Blokkeren/vertragen bij overschrijding**
- Retourneer HTTP 429 status bij overschrijding
- `Retry-After` header geeft aan wanneer opnieuw proberen
- Toon resterende tijd tot reset
### 4. **Extra mogelijkheden voor uitbreiding:**
**Blokkeren voor langere periode:**
```php
public function blockClient($identifier, $blockTime = 3600) {
$key = "blocked:{$identifier}";
$this->redis->setex($key, $blockTime, 'blocked');
}
public function isBlocked($identifier) {
return $this->redis->exists("blocked:{$identifier}");
}
```
**Gestaffelde limieten:**
```php
public function checkTieredLimit($identifier) {
$hourly = $this->checkLimit($identifier);
$daily = $this->checkLimit($identifier . ':daily', 1000, 86400);
return min($hourly, $daily);
}
```
**Headers toevoegen voor client-info:**
```php
header('X-RateLimit-Limit: ' . $this->limit);
header('X-RateLimit-Remaining: ' . $result['remaining']);
header('X-RateLimit-Reset: ' . $result['reset']);
```
Zorg ervoor dat Redis server draait en de PHP Redis extensie is geïnstalleerd (`pecl install redis`).