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