Bloc Note rapide
#!/bin/bash
# --------------------------------------------------
# Cron API – rate‑limit (30 req/min) → 429 Too Many Requests
# --------------------------------------------------
# ---------- Configuration ----------
MAX_PER_MIN=30 # nombre max de requêtes par minute
RATEFILE="/var/lib/cron_api/ratelimit"
# ---------- Fonctions ----------
# Retourne le timestamp (epoch) actuel
now() { date +%s; }
# Nettoie les anciennes entrées du fichier rate‑limit
cleanup_ratefile() {
local now_ts=$(now)
# Si le fichier existe, on garde uniquement les lignes < 60s d'ancienneté
if [[ -f "$RATEFILE" ]]; then
# On lit chaque ligne : epoch|count
while IFS='|' read -r ts cnt; do
# Si l'entrée a plus de 60s, on la ignore (fenêtre expirée)
(( now_ts - ts > 60 )) && continue
echo "$ts|$cnt"
done < "$RATEFILE" > "${RATEFILE}.tmp"
mv "${RATEFILE}.tmp" "$RATEFILE"
fi
}
# Retourne le nombre d’appels valides dans la fenêtre courante
get_current_count() {
local cnt=0
if [[ -f "$RATEFILE" ]]; then
while IFS='|' read -r ts cnt; do
(( now_ts - ts <= 60 )) && ((cnt+=cnt))
done < "$RATEFILE"
fi
echo "$cnt"
}
# Incrémente le compteur et réécrit le fichier (appelé après validation)
increment_and_store() {
local new_ts=$(now)
# Si le fichier est vide ou la fenêtre a expiré, on recommence à 1
if [[ ! -s "$RATEFILE" ]] || (( $(now) - $(cut -d'|' -f1 "$RATEFILE") > 60 )); then
echo "${new_ts}|1" > "$RATEFILE"
else
# On incrémente le compteur de la première entrée (ou on en crée une nouvelle)
local first_ts=$(cut -d'|' -f1 "$RATEFILE")
if (( $(now) - first_ts > 60 )); then
# Nouvelle fenêtre : on repart à 1
echo "${new_ts}|1" > "$RATEFILE"
else
# On incrémente le compteur existant
local new_cnt=$(( $(cut -d'|' -f2 "$RATEFILE") + 1 ))
echo "${first_ts}|${new_cnt}" > "$RATEFILE"
fi
fi
}
# ---------- Middleware de rate‑limit ----------
cleanup_ratefile # nettoie les entrées expirées
current_count=$(get_current_count)
if (( current_count >= MAX_PER_MIN )); then
# Trop de requêtes -> renvoyer 429 + JSON d’erreur
printf "Status: 429 Too Many Requests\r\n"
printf "Content-Type: application/json\r\n\r\n"
cat <<EOF
{
"error": "Rate limit exceeded. Try again later."
}
EOF
exit 0 # arrêt du script CGI (apache ne lit rien d’autre)
fi
# Si on arrive ici, on peut continuer le traitement habituel
increment_and_store # incrémente le compteur
# --------------------------------------------------
# Votre logique métier habituelle (exemple)
# --------------------------------------------------
# Exemple : lire le fichier de logs de cron et renvoyer du JSON
# (remplacez par votre logique réelle)
# 1) Récupérer la dernière ligne du log de cron (ou syslog)
# Ici on suppose que le fichier de log est /var/log/cron.log
CRON_LOG="/var/log/cron.log"
if [[ -r "$CRON_LOG" ]]; then
# Extraire la dernière ligne qui contient notre job (exemple : "myjob")
LAST_RUN=$(grep -m1 "myjob" "$CRON_LOG" | tail -n1)
# Si aucune ligne trouvée → état "not run"
if [[ -z "$LAST_RUN" ]]; then
STATUS="{\"state\":\"not_run\",\"last\":\"never\"}"
else
# Exemple d'extraction : date/heure + code de sortie
# Supposons que le format soit: "Jun 12 08:34:56 server CRON[12345]: (myuser) CMD"
# Vous pouvez adapter l'extraction selon votre format de log
LAST_TIME=$(echo "$LAST_RUN" | awk '{print $1,$2,$3}')
EXIT_CODE=$(( RANDOM % 4 )) # placeholder
STATUS="{\"state\":\"last_run\",\"when\":\"$LAST_TIME\",\"exit_code\":$EXIT_CODE}"
fi
else
STATUS='{"error":"log not found"}'
fi
# ---------- Envoi de la réponse JSON ----------
printf "Status: 200 OK\r\n"
printf "Content-Type: application/json\r\n\r\n"
printf "%s\r\n" "$STATUS"
exit 0