Rate Limiting ist essentiell, um deine APIs und Seiten vor Missbrauch, Brute-Force-Angriffen und übermäßiger Nutzung zu schützen. Cloudflare Workers bietet ein integriertes Rate Limiting Binding, das es einfach macht, Rate Limiting am Edge zu implementieren.
In diesem Leitfaden lernst du, wie du Rate Limiting in Astro mit Cloudflares Rate Limiting API implementierst, sowohl global über Middleware als auch auf Endpoint-Ebene.
Voraussetzungen
- Node.js 20 oder neuer
- Ein Cloudflare Konto
Eine neue Astro-Anwendung erstellen
Lass uns mit der Erstellung eines neuen Astro-Projekts beginnen. Führe den folgenden Befehl aus:
npm create astro@latest my-ratelimit-astro-appWenn du gefragt wirst, wähle:
Use minimal (empty) templatewenn du gefragt wirst, wie du das neue Projekt starten möchtest.Yeswenn du gefragt wirst, ob du Abhängigkeiten installieren möchtest.Yeswenn du gefragt wirst, ob du ein Git-Repository initialisieren möchtest.
Sobald das erledigt ist, wechsle in das Projektverzeichnis:
cd my-ratelimit-astro-appnpm install wranglernpm run devDie App sollte auf localhost:4321 laufen.
Cloudflare Adapter in dein Astro-Projekt integrieren
Um dein Astro-Projekt auf Cloudflare Workers zu deployen und Cloudflare KV zu nutzen, musst du den Cloudflare Adapter installieren. Führe den folgenden Befehl aus:
npx astro add cloudflareWenn du gefragt wirst, wähle Yes für jeden Prompt.
Das Rate Limiting Binding konfigurieren
Füge das Rate Limiting Binding zu deiner wrangler.jsonc hinzu:
{ // ... "ratelimits": [ { "namespace_id": "1001", "name": "MY_RATE_LIMITER", "simple": { "limit": 100, "period": 60 } } ]}Diese Konfiguration:
- Erstellt einen Rate Limiter namens
MY_RATE_LIMITER - Erlaubt 100 Anfragen pro 60 Sekunden pro eindeutigem Schlüssel
- Verwendet
namespace_idum Rate Limit Zähler zu isolieren
Aktualisiere deine src/env.d.ts um TypeScript-Definitionen hinzuzufügen:
/// <reference types="astro/client" />
type RateLimiter = { limit: (options: { key: string }) => Promise<{ success: boolean }>}
type ENV = { MY_RATE_LIMITER: RateLimiter}
type Runtime = import('@astrojs/cloudflare').Runtime<ENV>
declare namespace App { interface Locals extends Runtime {}}Rate Limiting in Astro Middleware
Um Rate Limiting global (oder für bestimmte Routen) anzuwenden, erstelle eine Middleware-Datei unter src/middleware.ts:
import { defineMiddleware } from 'astro:middleware'
// Routen mit Rate Limitingconst RATE_LIMITED_ROUTES = ['/']
export const onRequest = defineMiddleware(async (context, next) => { const { url, request, locals } = context const pathname = url.pathname
// Prüfe, ob Route Rate Limiting haben soll const shouldRateLimit = RATE_LIMITED_ROUTES.some((route) => pathname === (route) )
if (!shouldRateLimit) { return next() }
// Überspringe, wenn Rate Limiter nicht verfügbar ist (lokale Entwicklung) const rateLimiter = locals.runtime?.env?.MY_RATE_LIMITER if (!rateLimiter) { console.log('[Rate Limit] Binding nicht verfügbar, überspringe') return next() }
// Verwende Client-IP als Rate Limit Schlüssel const clientIP = request.headers.get('CF-Connecting-IP') || 'unknown'
try { const { success } = await rateLimiter.limit({ key: clientIP })
if (!success) { return new Response( JSON.stringify({ error: 'Zu viele Anfragen', message: 'Rate Limit überschritten. Bitte versuche es später erneut.', }), { status: 429, headers: { 'Content-Type': 'application/json', 'Retry-After': '60', }, } ) } } catch (error) { console.error('[Rate Limit] Fehler:', error) // Bei Fehler, erlaube die Anfrage (fail open) }
return next()})
Diese Middleware:
- Prüft, ob die aktuelle Route Rate Limiting haben soll
- Verwendet die IP-Adresse des Clients als Rate Limit Schlüssel
- Gibt eine
429 Too Many RequestsAntwort zurück, wenn das Limit überschritten wird
Rate Limiting in einem API Endpoint
Für granularere Kontrolle, wende Rate Limiting direkt in deinen API-Endpunkten an. Erstelle src/pages/api/data.ts:
import type { APIContext } from 'astro'
export async function GET({ request, locals }: APIContext) { const rateLimiter = locals.runtime?.env?.MY_RATE_LIMITER
if (rateLimiter) { const clientIP = request.headers.get('CF-Connecting-IP') || 'unknown'
const { success } = await rateLimiter.limit({ key: clientIP })
if (!success) { return new Response( JSON.stringify({ error: 'Rate Limit überschritten' }), { status: 429, headers: { 'Content-Type': 'application/json' }, } ) } }
// Deine Endpoint-Logik hier return new Response( JSON.stringify({ message: 'Erfolg', data: { timestamp: Date.now() } }), { status: 200, headers: { 'Content-Type': 'application/json' }, } )}
Dieser Endpoint:
- Verwendet die IP-Adresse des Clients als Rate Limit Schlüssel
- Gibt eine
429 Rate Limit ExceededAntwort zurück, wenn das Limit überschritten wird
Benutzerdefinierte Rate Limit Schlüssel
Du kannst verschiedene Schlüssel für unterschiedliche Rate Limiting Strategien verwenden:
// Rate Limit nach Benutzer-ID (für authentifizierte Routen)const userId = locals.user?.idconst { success } = await rateLimiter.limit({ key: `user:${userId}` })
// Rate Limit nach IP + Endpoint Kombinationconst key = `${clientIP}:${url.pathname}`const { success } = await rateLimiter.limit({ key })
// Rate Limit nach API-Schlüsselconst apiKey = request.headers.get('X-API-Key') || 'anonymous'const { success } = await rateLimiter.limit({ key: `api:${apiKey}` })Auf Cloudflare Workers deployen
Deploye deine Rate-Limiting-aktivierte Astro-Anwendung in die Produktion:
# Projekt bauennpm run build
# Auf Cloudflare Workers deployennpx wrangler deployFazit
Durch die Implementierung von Rate Limiting mit Cloudflare Workers in deiner Astro-App blockierst du effektiv missbräuchliche Anfragen - wie Brute-Force-Angriffe, API-Übernutzung und DDoS-Versuche am Edge. Dies verbessert sowohl die Sicherheit als auch die Performance deiner Anwendung, indem Bedrohungen gestoppt werden, bevor sie deine Anwendungslogik erreichen.